协议层
串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据,其组成见图 。
波特率
本章中主要讲解的是串口异步通讯,异步通讯中由于没有时钟信号 (如前面讲解的 DB9 接口中是没有时钟信号的),所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码,图 20_6 中用虚线分开的每一格就是代表一个码元。常见的波特率为 4800、9600、115200 等。
通讯的起始和停止信号
串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示,只要双方约定一致即可。
有效数据
在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为 5、6、7 或 8 位长。
数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验 (odd)、偶校验(even)、0 校验 (space)、1 校验 (mark) 以及无校验 (noparity)。
奇校验要求有效数据和校验位中“1”的个数为奇数,比如一个 8 位长的有效数据为:01101001,此时总共有 4 个“1”,为达到奇校验效果,校验位为“1”,最后传输的数据将是 8 位的有效数据加上 1 位的校验位总共 9 位。偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,比如数据帧:11001010,此时数据帧“1”的个数为 4 个,所以偶校验位为“0”。0 校验是不管有效数据中的内容是什么,校验位总为“0”,1 校验是校验位总为“1”。
//初始化
/*使能串口接收断 */ __HAL_UART_ENABLE_IT(&UartHandle,UART_IT_RXNE);
/*使能串口空闲中断 */ __HAL_UART_ENABLE_IT(&UartHandle,UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(&UartHandle);
//中断
void DEBUG_USART_IRQHandler(void)
{
if(__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_IDLE ) != RESET) //中断中判断产生了空闲中断标志认为一轮结束
{
Rxflag = 1;
Rxlen += BUFFSIZE - UartHandle.RxXferCount; //累计达不到BUFFSIZE个数的部分 __HAL_UART_CLEAR_IDLEFLAG(&UartHandle);
HAL_UART_AbortReceive_IT(&UartHandle);
return ;
}
HAL_UART_IRQHandler(&UartHandle);
}
//main.c
/*调用printf函数,因为重定向了fputc,printf的内容会输出到串口*/
printf("欢迎使用野火开发板\n");
/*自定义函数方式*/
Usart_SendString( (uint8_t *)"串口接收不定长字节,请查看程序内注释\r\n" );
/*开启第一次接收状态*/
HAL_UART_Receive_IT(&UartHandle,(uint8_t*),);
//查询
char ch;
while(1)
{ch=getchar();
printf("接收到字符:%c\n",ch);
}
//中断
__HAL_UART_ENABLE_IT(&UartHandle,UART_IT_RXNE);
void DEBUG_USART_IRQHandler(void)
{ uint8_t ch=0; if(__HAL_UART_GET_FLAG( &UartHandle, UART_FLAG_RXNE ) != RESET)
{ ch=( uint16_t)READ_REG(UartHandle.Instance->DR);
WRITE_REG(UartHandle.Instance->DR,ch);
}
}