baiguo 发表于 2009-8-14 16:17:36

C#串口通信求助

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_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)
                        rx_state = LOW_ADDR_STATE;
                  else
                        rx_state = FRAME_HEAD_STATE;                  
                  break;
                case LOW_ADDR_STATE:
                  if (rx_temp == frame)
                  {
                        rx_state = CMD_DATA_STATE;
                        rx_data_cnt = 2;
                  }
                  else
                        rx_state = FRAME_HEAD_STATE;
                  break;
                case CMD_DATA_STATE:
                  buffer = 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;
            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进入接收缓冲区就触发一次还是....?

Appcat 发表于 2009-8-14 16:27:19

上位机一般是消息循环机制,这个和中断不一样,不会一个字符就产生一个消息的,所以上位机一定是##2的办法,看看缓冲区里边有多少字节,然后一起取走处理。

Alexkey 发表于 2009-8-14 16:39:21

看着楼主的代码有点抓狂,感觉好乱啊

baiguo 发表于 2009-8-14 16:41:41

可现场上位机和下位机是通过无线模块连接的,可能会有几台上下位同时工作,如果上位机不能及时的抛除非本机寻址的下位机返回数据,那结果....
页: [1]
查看完整版本: C#串口通信求助