搜索
bottom↓
回复: 3

C#串口通信求助

[复制链接]

出0入0汤圆

发表于 2009-8-14 16:17:36 | 显示全部楼层 |阅读模式
pc与mcu通信,每帧为7byte 帧格式为起始位0x80--上位机地址---下位机地址---传感器编号---命令---数据1----数据0
mcu端处理流程如下:(中断接收)
  (1)接收帧头,如接收正确,状态机跳到(2),否则状态机停留(1)
  (2)接收上位机地址,其余据上类推....
当一帧数据接收完成后,rx_receive_finished_flag置1  代码如下:

void USART1_IRQHandler(void)
{
    if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)
    {
        USART_ClearFlag(USART1,USART_FLAG_RXNE);
        rx_temp=USART_ReceiveData(USART1);
               
        switch(rx_state)
        {
        case FRAME_HEAD_STATE:
            if(rx_temp==0x80)
                rx_state=UP_ADDR_STATE;
            break;
        case UP_ADDR_STATE:
            if(up_addr==0x00)
            {
                up_addr=rx_temp;
                rx_state=LOW_ADDR_STATE;
            }
            else if(rx_temp==up_addr)
                rx_state=LOW_ADDR_STATE;
            else
                rx_state=FRAME_HEAD_STATE;
            break;
        case LOW_ADDR_STATE:
            if(rx_temp==low_addr)
                rx_state=SENSOR_ADDR_STATE;
            else
                rx_state=FRAME_HEAD_STATE;
            break;
        case SENSOR_ADDR_STATE:
            curr_sensor_addr=rx_temp;
            rx_state=CMD_DATA_STATE;
            rx_cnt=2;
            break;
        case CMD_DATA_STATE:
            rx_data[rx_cnt]=rx_temp;
            if(rx_cnt>0)
                rx_cnt--;
            else
            {
                rx_cnt=0;
                rx_receive_finished_flag=1;
                rx_state=FRAME_HEAD_STATE;
            }
            break;
        default:
            rx_state=FRAME_HEAD_STATE;
            break;
        }

    }
}

由于不熟悉上位机软件,故将上述方法借鉴与C#的串口编程中。(上位机发送一帧数据,下位机收到后即返回收到的那帧数据)
自认为下面上位机接收是基于中断方式,当一帧数据接收完成后 rx_receive_finished_flag = true;
(定时器在发送数据时启动,200ms后检测rx_receive_finished_flag == true? 并输出相应消息,用以提示下位机是否
正确收到数据帧)

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)     -----------##1
        {                       
            byte rx_temp = 0;
            rx_temp = (byte)serialPort1.ReadByte();
            serialPort1.DiscardInBuffer();
            
            switch (rx_state)
            {
                case FRAME_HEAD_STATE:
                    if (rx_temp == 0x80)
                        rx_state = UP_ADDR_STATE;                    
                    break;
                case UP_ADDR_STATE:
                    if (rx_temp == frame[1])
                        rx_state = LOW_ADDR_STATE;
                    else
                        rx_state = FRAME_HEAD_STATE;                    
                    break;
                case LOW_ADDR_STATE:
                    if (rx_temp == frame[2])
                    {
                        rx_state = CMD_DATA_STATE;
                        rx_data_cnt = 2;
                    }
                    else
                        rx_state = FRAME_HEAD_STATE;
                    break;
                case CMD_DATA_STATE:
                    buffer[rx_data_cnt] = rx_temp;
                    if (rx_data_cnt > 0)
                        rx_data_cnt--;
                    else
                    {
                        rx_data_cnt = 0;
                        rx_receive_finished_flag = true;
                        rx_state = FRAME_HEAD_STATE;
                    }
                    break;
            }            

        }

很遗憾,每次发送后定时器弹出的消息都是“ERROR”,而下位机显示屏上显示的数据却是正确的接收数据----显然上位机接收处理部分出了问题,在哪里?
该怎么修正??

将上位机接收部分改为
//=========================================================================================
        //接收数据
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)   ----------##2
        {
            int bytes = serialPort1.BytesToRead;
            byte[] buffer = new byte[bytes];
            serialPort1.Read(buffer, 0, buffer.Length);
            string str = ByteArrayToHexString(buffer).Trim();   
            if (textBox2.Text == "")
                textBox2.Text = str;
            else
                textBox2.Text = textBox2.Text + " " + str;            
        }
文本显示数据和发送数据是一致的。
糊涂了,不清楚##1为什么不对,serialPort1_DataReceived是每有一byte进入接收缓冲区就触发一次还是....?

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出1070入962汤圆

发表于 2009-8-14 16:27:19 | 显示全部楼层
上位机一般是消息循环机制,这个和中断不一样,不会一个字符就产生一个消息的,所以上位机一定是##2的办法,看看缓冲区里边有多少字节,然后一起取走处理。

出0入0汤圆

发表于 2009-8-14 16:39:21 | 显示全部楼层
看着楼主的代码有点抓狂,感觉好乱啊

出0入0汤圆

 楼主| 发表于 2009-8-14 16:41:41 | 显示全部楼层
可现场上位机和下位机是通过无线模块连接的,可能会有几台上下位同时工作,如果上位机不能及时的抛除非本机寻址的下位机返回数据,那结果....
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-1 03:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表