一、串口通信原理
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);
}