串口整个东西可以说但凡你要碰单片机,想做点上点档次的东西的话那你就包用它的。32的串口配置并不难,哪怕是比起51其实也难不到哪去。
目录
一.通信基础
1.通信方式
1.你要知道什么叫:半双工通信;全双工通信;单工通信;这些的定义是什么就可以了。因为再配置中其实串口是可以配置成其中的某一种的。当然了,全双工是最常用的一种。由于都比较简单,这里就不多赘述。
2.同步通信与异步通信:
定义是这样的:
同步通信:发送和接收双方按照预定的时钟节拍进行数据的发送和接收,双方的操作严格同步。 异步通信:双方不需要严格的时钟同步,每一帧数据通过起始位和停止位分割,接收方可以 独立地识别每个数据块。
让我来暴力的给你总结一句话:同步的有时钟线,异步的咩有时钟线。
2.通信速率
比特率:比特率是指在单位时间内可以发送的二进制数量,也就是信息发送速率。
波特率:波特率本质上是单位时间内信号调制的次数,决定了单位时间内能发送出多少码元。
二.串口基础
1.串口的数据帧结构(协议)
启动位:它是一个逻辑0(低电平)的信号。告诉接收方数据传输即将开始。
停止位:停止位是一个逻辑高电平1,用于指示数据传输的结束。
有效数据位:就是二进制数据,由一堆高低电平组成。这里有个重点是:串口是按位发送的,而这里是低位先发送。
校验位:校验数据完整性的,主要看数据包中的1的数量和对用的是否一致。但是不咋用因为不准确,不准确了自然用的就少了。
2.STM32中的USART
1.可以是异步也可以是同步
2.拥有一个硬件流控制器,其实就是用硬件来强行匹配接--收的速率匹配来降低丢包率的。
3.拥有一个波特率发生器,一般最高可以4.5MB/s
4.USART的框图:
5.USART的常用寄存器的位:
其中:
TXE 发送空中断
TC 发送完成中断
RXNE 接收非空中断(读取后自动RESET)
IDLE 空闲中断
TE&RE 发送/接收使能
其中空闲中断由软件复位。
三.串口程序配置
1.接收的同时发送一位数据
串口的配置方式和GPIO,TIM等外设配置一致的相似:
void uart_init(uint32_t bundrate){
uart_handle.Instance = USART1;
uart_handle.Init.BaudRate = bundrate;
uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
uart_handle.Init.Mode = UART_MODE_TX_RX;
uart_handle.Init.Parity = UART_PARITY_NONE;
uart_handle.Init.StopBits = UART_STOPBITS_1;
uart_handle.Init.WordLength = UART_WORDLENGTH_8B;
HAL_UART_Init(&uart_handle);
}
随后是非常经典的MSP配置:
void HAL_UART_MspInit(UART_HandleTypeDef *huart){
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
//TX初始化为复用推挽输出
GPIO_InitTypeDef gpio_init;
gpio_init.Mode = GPIO_MODE_AF_PP;
gpio_init.Pin = GPIO_PIN_9;
gpio_init.Pull = GPIO_PULLUP;
gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&gpio_init);
//RX初始化为浮空输入
gpio_init.Mode = GPIO_MODE_AF_INPUT;
gpio_init.Pin = GPIO_PIN_10;
HAL_GPIO_Init(GPIOA,&gpio_init);
HAL_NVIC_SetPriority(USART1_IRQn,2,2);
HAL_NVIC_EnableIRQ(USART1_IRQn);
__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);
__HAL_UART_ENABLE_IT(huart,UART_IT_IDLE);
}
这里有个重点是GPIO的两个口一个是推挽输出一个是浮空输入,如果你基础就知道使用推挽输出是为了保证数据逻辑电平不被GPIO内设的电压影响,使用浮空输入也是如此,把控制电压的控制权交出去。如果你不知道原因,也可以直接用以下推荐:
中断部分:
void USART1_IRQHandler(){
uint8_t data;
if(__HAL_UART_GET_FLAG(&uart_handle,UART_FLAG_RXNE) != RESET){
HAL_UART_Receive(&uart_handle,&data,1,500); //接收
HAL_UART_Transmit(&uart_handle,&data,1,500); //发送
}
}
2.非常经典的不等长数据配置
配置方面一样,唯一不同的就是这里使用了空闲中断,该中断在被使能后会在接收完所有数据后空闲时发起一个中断,检测该中断是否触发就可以完整的收取数据:
void USART1_IRQHandler(){
uint8_t rev_data;
if(__HAL_UART_GET_FLAG(&uart_handle,UART_FLAG_RXNE) != RESET){
HAL_UART_Receive(&uart_handle,&data,1,1000);
rev_buf[len++] = rev_data;
}
if(__HAL_UART_GET_FLAG(&uart_handle,UART_FLAG_IDLE) != RESET){
HAL_UART_Transmit(&uart_handle,&rev_data,sizeof(rev_buf),500);
memset(rev_buf,0,sizeof(rev_buf));
len = 0;
__HAL_UART_CLEAR_IDLEFLAG(&uart_handle); //软件清零
}
}
注意:sizeof对数组使用时返回的是整个数组的字节数,这里可以使用sizeof直接测量数组的长度是因为串口的数据为设置位8位,所以在定义时使用了uint8_t。故而只是数值上相等。
好了就这些,祝你看完就会。
点个关注8