历史上的今天
今天是:2024年10月12日(星期六)
2019年10月12日 | STM32F1笔记(三)UART/USART
2019-10-12 来源:eefocus
UART:Universal Asynchronous Receiver/Transmitter(通用异步收/发器)
USART:Universal Synchronous/Asynchronous Receiver/Transmitter(通用同步/异步串行收/发器)
从命名即可看出USART就是UART的基础上添加了同步功能。通常把UART/USART称为串口。
串口包含TLL电平和232的串口,485等电气特性的串口。232、485通常应用于工业。
串口配置的一般步骤可以参考正点原子的总结:
1、串口时钟使能,GPIO时钟使能;
2、串口复位;(我不知道这一步的意义,去掉似乎也没影响,求大神指点)
3、GPIO端口模式的配置;
4、串口参数初始化;
5、初始化NVIC并开启中断;
6、使能串口;
7、编写中断服务函数。
配置示例:
void Usart3_Init(unsigned int BaudRate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
USART_DeInit(USART3);
//USART3_TX GPIOB.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//USART3_RX GPIOB.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitStructure.USART_BaudRate = BaudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_Cmd(USART3, ENABLE);
}
注意:在此示例中GPIO的速率配置为50M,其实没必要那么高,可降低至2M。速率越高,噪声越大,功耗越高。
在配置代码中,开启了接收中断。在日常串口使用中,都会规定通信协议。通信协议的解析,通常在中断服务函数里进行。
通信协议通常由帧头,数据,帧尾三部分组成。
帧头不正确,不继续处理后续接收到的内容。
帧尾不正确,对数据不进行处理。
示例:

帧头由两部分组成,校验信息和数据长度。示例中断校验信息,赋值给unsigned char的变量,相加后为0。这是特殊的帧头。
unsigned char chr = 0;
chr += (0xAA + 0xBB + 0xCC + 0xDD + 0xEE + 0x04);
printf("chr=%Xn", chr);
![]()
数据长度通常只指数据的长度,不包含帧头校验信息和帧尾的长度。
帧尾可以是CRC等校验方式。可包含长度也可不包含,计算数据的CRC。目的是确保数据的一致性。
串口中断服务函数示例:
void USART3_IRQHandler(void)
{
if(USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == SET)
{
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
g_usart3_recv_data = USART_ReceiveData(USART3);
switch(g_usart3_recv_state)
{
case USART3_RECV_FIRST_FRAME_HEAD:
if(MKLM_FIRST_FRAME_HEAD == g_usart3_recv_data)
{
g_usart3_recv_state = USART3_RECV_SECOND_FRAME_HEAD;
}
else
{
g_usart3_recv_state = USART3_RECV_FIRST_FRAME_HEAD;
}
break;
case USART3_RECV_SECOND_FRAME_HEAD:
if(MKLM_SECOND_FRAME_HEAD == g_usart3_recv_data)
{
g_usart3_recv_state = USART3_RECV_FIRST_LENGTH;
}
else
{
g_usart3_recv_state = USART3_RECV_FIRST_FRAME_HEAD;
}
break;
case USART3_RECV_FIRST_LENGTH:
g_Usart3_recv_struct.length = g_usart3_recv_data;
g_Usart3_recv_struct.length <<= 8;
g_usart3_recv_state = USART3_RECV_SECOND_LENGTH;
break;
case USART3_RECV_SECOND_LENGTH:
g_Usart3_recv_struct.length |= g_usart3_recv_data;
g_usart3_recv_length = 0;
g_usart3_recv_state = USART3_RECV_ADDRESS;
break;
case USART3_RECV_ADDRESS:
g_Usart3_recv_struct.address = g_usart3_recv_data;
g_usart3_recv_length++;
g_usart3_recv_state = USART3_RECV_ORDER;
break;
case USART3_RECV_ORDER:
g_Usart3_recv_struct.order = g_usart3_recv_data;
g_usart3_recv_length++;
g_usart3_recv_state = USART3_RECV_ACTION;
break;
case USART3_RECV_ACTION:
g_Usart3_recv_struct.action = g_usart3_recv_data;
g_usart3_recv_length++;
g_usart3_recv_state = USART3_RECV_FIRST_CRC;
break;
case USART3_RECV_FIRST_CRC:
g_Usart3_recv_struct.crc16 = g_usart3_recv_data;
g_Usart3_recv_struct.crc16 <<= 8;
g_usart3_recv_length++;
g_usart3_recv_state = USART3_RECV_SECOND_CRC;
break;
case USART3_RECV_SECOND_CRC:
g_Usart3_recv_struct.crc16 |= g_usart3_recv_data;
g_usart3_recv_length++;
if(g_usart3_recv_length == g_Usart3_recv_struct.length)
{
g_recv_status = RECEIVE_OK;
}
else
{
g_recv_status = RECEIVE_LENGTH_ERROR;
}
g_usart3_recv_flag = USART3_RECV_SECCESS;
g_usart3_recv_length = 0;
g_usart3_recv_state = USART3_RECV_FIRST_FRAME_HEAD;
break;
default:
break;
}
}
}
STM32使用printf的方法。
在魔术棒里勾选Use MicroLIB(默认是不勾选的)

以串口2为例,在串口2相关.c里(可在任何位置,为防混乱放在需要配置给printf的串口文件里)
加入以下代码(别忘了添加包含头文件stdio.h)
#include int fputc(int ch, FILE* stream) { while (!(USART2->SR & USART_FLAG_TXE)); USART_SendData(USART2, (uint8_t)ch); return ch; } 就可以调用printf了,调用前别忘了相关串口要初始化。 Uart2_Init(9600); while(1) { printf("Hello World!rn"); delay_ms(100); } 通过串口助手可以看到现象
史海拾趣
|
摘要:航空蓄电池野外充放电车的设计与研制,采用电子集成化模块和开发电源技术,使航空蓄电池野外充放电车的功率大、体积小、稳态精度高。通过在航空兵部队的使用,证明移动式综合充放电设备具重要的经济和军事效益。 关键词: ...… 查看全部问答> |
|
转自:NI 概览 为您下一个嵌入式项目或想法创建功能原型系统是得到预算和从高层管理获得批准的重要步骤。在开始原型开发之前,考虑一下您所有需要的工具。另一个需要记住的重要原则是原型开发应该足够快速,不应该在原型系统上花费过多的时间,投 ...… 查看全部问答> |
|
设计了一个5.0V输入,可调输出buck电路,1.5M固定频率但是在较大电流输出,并直接开关电源的时候,时不时出现不稳定情况不稳定时前几个占空比很大,直至输出电压过高仿真上非常稳定,PM也足够这可能是什么原因造成的?请教各位!… 查看全部问答> |
|
在一个VxWorks操作系统中,如何通过网络驱动网络打印机(如HP LaserJet 5200网络激光打印机)打一份文本文件。 大家可以给出一些启发性的意见。… 查看全部问答> |
|
我用的是MSP1121的,在XIN和XOUT两端接一个4M晶振。如下设置后,但是就是不起振。 不知道是什么原因? BCSCTL1 |= XTS; // ACLK= LFXT1= 高频晶体振荡器 do { IFG1 &= ~OFI ...… 查看全部问答> |




