一、串口通信原理

1.什么是UART

​ UART : Universal Asynchronous Receiver/Transmitter 通用异步收发器 ​ 一种常用也是最简单的串行数据传输协议。数据线只需要两根就可以实现全双工。 ​ Tx:发送数据线 ​ Rx:接收数据线 ​ A B ​ Tx <-----------> Rx ​ Rx <-----------> Tx ​ GND<-----------> GND

2.上位机与下位机

​ 模块之间的通信,根据其在系统中的功能与作用可分为上位机 与 下位机。

上位机: 把处理性能强的计算机称为上位机。数据的统一处理都在上位机完成。

下位机: 把数据采集和发送的终端,处理性能单一的计算机,称为下位机。

一般一个上位机会对应多个下位机,这种模式可以使数据处理的更加全面,同时也大大降低成本。

3.UART数据帧

UART protocol 串口协议 串口发送和接收数据是以帧为单位,Frame

1帧(Frame) = 1start bit(起始位) + 5~9bits数据位 + 0/1bit校验位 + stop bits(0.5,1,1.5)停止位
起始位:一个周期的低电平
数据位:5~9bits数据位,具体是多少bits,需要双方协商,并且传送先传送最低位(LSB)
校验位:
    0bit:没有校验
    1bit:有校验
        奇校验:数据位+校验位的这一段数据里的1的个数是奇数。
        偶校验:数据位+校验位的这一段数据里的1的个数是偶数。
停止位:高电平
    
    1个停止位
            
Baudrate(波特率):传输速率,即没一个秒传输了多少个bit位
    4800
    9600
    115200bps: bits per second

二、串口配置

1. 串口初始化相关的结构体halUARTCfg_t

typedef struct
{
  bool                configured;//是否设置串口
  uint8               baudRate; //波特率设置
  bool                flowControl;//控制流设置
  uint16              flowControlThreshold;//RX缓存安全字节数(了解)
  uint8               idleTimeout;//RX来数据超时时间(了解)
  halUARTBufControl_t rx;//接收数据长度
  halUARTBufControl_t tx;//发送数据长度
  bool                intEnable;//中断使能
  uint32              rxChRvdTime;//接收数据时间
  halUARTCBack_t      callBackFunc;//回调函数
}halUARTCfg_t;

2. 串口初始化示例

static void InitUart(void)
{
	halUARTCfg_t   uartConfig;
	uartConfig.configured           = TRUE;  //
	uartConfig.baudRate             = HAL_UART_BR_38400;
	uartConfig.flowControl          = FALSE;
	uartConfig.flowControlThreshold = 64; 
	uartConfig.rx.maxBufSize        = 128;  
	uartConfig.tx.maxBufSize        = 128;  
	uartConfig.idleTimeout          = 6;    
	uartConfig.intEnable            = TRUE;                
	uartConfig.callBackFunc         = SerialApp_CallBack;   
	HalUARTOpen (SERIAL_APP_PORT, &uartConfig);   
}

3.串口实现

​ 串口的读操作函数为HalUARTRead(),主要功能是读取上位机通过串口发送至设备节点的数据。

​ uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len) ​ @port:串口端口的设置,可以设置为串口0或串口1; ​ @buf:数据缓冲区; ​ @len:数据长度。 ​ 返回值:实际成功读取的字节数

串口的操作函数为HalUARTRead(),主要功能是读取上位机通过串口发送至设备节点的数据。

uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len)
{
 
#if (HAL_UART_DMA == 1)
  if (port == HAL_UART_PORT_0)  return HalUARTReadDMA(buf, len);
#endif
#if (HAL_UART_DMA == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTReadDMA(buf, len);
#endif
#if (HAL_UART_ISR == 1)
  if (port == HAL_UART_PORT_0)  return HalUARTReadISR(buf, len);
#endif
#if (HAL_UART_ISR == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTReadISR(buf, len);
#endif
 
#if HAL_UART_USB
  return HalUARTRx(buf, len);
#else
  return 0;
#endif
}

串口的操作函数为HalUARTWrite(),主要功能是实现向上位机或其他设备通过串口发送数据。 uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len) @port:串口端口的设置,可以设置为串口0或串口1; @buf:数据缓冲区; @len:数据长度。 返回值:实际成功发送的字节数

uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
{ 
#if (HAL_UART_DMA == 1)
  if (port == HAL_UART_PORT_0)  return HalUARTWriteDMA(buf, len);
#endif
#if (HAL_UART_DMA == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTWriteDMA(buf, len);
#endif
#if (HAL_UART_ISR == 1)
  if (port == HAL_UART_PORT_0)  return HalUARTWriteISR(buf, len);
#endif
#if (HAL_UART_ISR == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTWriteISR(buf, len);
#endif
 
#if HAL_UART_USB
  HalUARTTx(buf, len);
  return len;
#else
  return 0;
#endif
}

三、程序设计

void SerialApp_CallBack(uint8 port, uint8 event)   //接收数据会触发
{
    unsigned char buf[32]={0};
    HalUARTRead(HAL_UART_PORT_0,buf,32);
    if(strcmp((char*)buf,"hello") == 0)
    {
        led_ctrl(LED0,LED_ON);
        led_ctrl(LED1,LED_ON);
    }
    else if(strcmp((char*)buf,"byebye") == 0)
    {
        led_ctrl(LED0,LED_OFF);
        led_ctrl(LED1,LED_OFF);
    }

}

static void InitUart(void)
{
	halUARTCfg_t   uartConfig;
	uartConfig.configured           = TRUE;  
	uartConfig.baudRate             = HAL_UART_BR_9600; //设置波特率
	uartConfig.flowControl          = FALSE;
	uartConfig.flowControlThreshold = 64; 
	uartConfig.rx.maxBufSize        = 128;  
	uartConfig.tx.maxBufSize        = 128;  
	uartConfig.idleTimeout          = 6;    
	uartConfig.intEnable            = TRUE;                
	uartConfig.callBackFunc         = SerialApp_CallBack;  //设置回调函数 
	HalUARTOpen (HAL_UART_PORT_0, &uartConfig);   
}

if ( events & GENERICAPP_MY_EVT1 )	//事件
  {//事件要做的事
    P1_0 = !P1_0;
    P1_1 = !P1_1;
    unsigned char str[32]={"hello,are you ok?\r\n"};
    HalUARTWrite(HAL_UART_PORT_0,str,strlen((char *)str));
    unsigned char temp[32];
    if(Start_DHT11() == 1)	//读取dht11数据
    {
      sprintf(temp,"temperature:%d,humidity:%d\r\n",temperature,humidity);
      HalUARTWrite(HAL_UART_PORT_0,temp,strlen((char *)temp));
    }
    else
    {
        HalUARTWrite(HAL_UART_PORT_0,"error\r\n",strlen("error\r\n"));
    }
    return (events ^ GENERICAPP_MY_EVT1);
  }