历史上的今天
返回首页

历史上的今天

今天是:2025年12月21日(星期日)

2022年12月21日 | STM32 USART串口的使用方法和程序

2022-12-21 来源:zhihu

通用同步异步收发器(USART)提供了一种灵活的方法来与使用工业标准NR 异步串行数据格式的外部设备之间进行全双工数据交换。 USART利用分数波特率发生器提供宽范围的波特率选择,支持同步单向通信和半双工单线通信。

1、STM32固件库使用外围设备的主要思路

在STM32中,外围设备的配置思路比较固定。首先是使能相关的时钟,一方面是设备本身的时钟,另一方面如果设备通过IO口输出还需要使能IO口的时钟;最后如果对应的IO口是复用功能的IO口,则还必须使能AFIO的时钟。

其次是配置GPIO,GPIO的各种属性由硬件手册的AFIO一章详细规定,较为简单。

接着相关设备需要如果需要使用中断功能,必须先配置中断优先级,后文详述。

然后是配置外围设备的相关属性,视具体设备而定,如果设备需要使用中断方式,必须使能相应设备的中断,之后需要使能相关设备。

最后如果设备使用了中断功能,则还需要填写相应的中断服务程序,在服务程序中进行相应操作。

2、UART的配置步骤(查询方式)

2.1、打开时钟

由于UART的TX和RX和AFIO都挂在APB2桥上,因此采用固件库函数RCC_APB2PeriphClockCmd()进行初始化。UARTx需要分情况讨论,如果是UART1,则挂在APB2桥上,因此采用RCC_APB2PeriphClockCmd()进行初始化,其余的UART2~5均挂在APB1上。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

2.2、GPIO初始化

GPIO的属性包含在结构体GPIO_InitTypeDef,其中对于TX引脚,GPIO_Mode字段设置为GPIO_Mode_AF_PP(复用推挽输出),GPIO_Speed切换速率设置为GPIO_Speed_50MHz;对于RX引脚,GPIO_Mode字段设置为GPIO_Mode_IN_FLOATING(浮空输入),不需要设置切换速率。最后通过GPIO_Init()使能IO口。

以下是GPIO设置的实例代码:

GPIO_InitTypeDef GPIO_InitStructure;

//USART1 Tx(PA.09) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

//USART1 Rx(PA.10) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

2.3、配置UART相关属性

通过结构体USART_InitTypeDef来确定。UART模式下的字段如下

USART_BaudRate:波特率,视具体设备而定

USART_WordLength:字长

USART_StopBits:停止位

USART_Parity:校验方式

USART_HardwareFlowControl:硬件流控制

USART_Mode:单/双工

最后设置。实例代码为:

//USART1配置

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate =9600;

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_Tx | USART_Mode_Rx;

USART_Init(USART1, &USART_InitStructure);

USART_Cmd(USART1, ENABLE);

别忘了最后要使用USART_Cmd()来启动设备UART1。

2.4、重定向print()函数。

intfputc(intch,FILE *f)

{

USART1->SR;//USART_GetFlagStatus(USART1, USART_FLAG_TC) 解决第一个字符发送失败的问题

//一个一个发送字符USART_SendData(USART1, (unsignedchar) ch);

//等待发送完成while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);

return(ch);

}

最后通过主函数直接输出即可。

intmain(void)

{

// USART1 config 9600 8-N-1 USART1_Config();

printf("hello world!");

}



3、UART的配置步骤(中断方式)

打开时钟、GPIO初始化、配置UART相关属性、重定向print()函数 与上面的相同。

3.1、中断优先级的配置

这是STM32比较奇怪的地方,在只有一个中断的情况下,仍然需要配置优先级,其作用是使能某条中断的触发通道。STM32的中断有至多两个层次,分别是先占优先级和从优先级,而整个优先级设置参数的长度为4位,因此需要首先划分先占优先级位数和从优先级位数,通过NVIC_PriorityGroupConfig()实现;

特定设备的中断优先级NVIC的属性包含在结构体NVIC_InitTypeDef中,其中字段NVIC_IRQChannel包含了设备的中断向量,保存在启动代码中;字段NVIC_IRQChannelPreemptionPriority为主优先级,NVIC_IRQChannelSubPriority为从优先级,取值的范围应根据位数划分的情况而定;最后NVIC_IRQChannelCmd字段是是否使能,一般定位ENABLE。最后通过NVIC_Init()来使能这一中断向量。实例代码如下:

//配置UART1接收中断voidNVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

/* Configure the NVIC Preemption Priority Bits */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

/* Enable the USARTy Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

3.2、中断的服务程序的设计

目前使用了UART的两个中断USART_IT_RXNE(接收缓存补空中断)和USART_IT_TXE(发送缓存空中断),前一个中断保证了一旦有数据接收到就进入中断以接收特定长度的数据,后一个中断表示一旦发完一个数据就进入中断函数,保证连续发送一段数据。一个设备的所有中断都包含在一个中断服务程序中,因此必须首先分清楚这次响应的是哪一个中断,使用USART_GetITStatus()函数确定;采用USART_ReceiveData()函数接收一个字节数据,采用USART_SendData()函数发送一个字节数据,当关闭中断时采用USART_ITConfig()失能响应的中断。实例程序:

voidUSART1_IRQHandler(void)

{

uint8_t ch;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

{

//ch = USART1->DR;ch = USART_ReceiveData(USART1);//接受数据printf("%c", ch );//返回打印 }

}

3.3、接收数据函数:

//重定向scanf函数到USART1intfgetc(FILE *f)

{

/*等待串口1输入数据*/while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

return(int)USART_ReceiveData(USART1);

}



4、 STM32串口在首次发送字符的时候,首字符丢失解决办法

网上关于发送字符的代码大多如下:

USART_SendData(USART1, (uint8_t)ch);

while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);

其实咋一看是说的通的,但是在仔细看手册的时候发现 TC 和 TXE 标志位在复位的时候被置1 ,这样第一次while循环就是没有用的。这样导致了首次第一个字符还没有被输出,就被后面的字符覆盖掉,造成实际看到的丢失现象。解决办法就很简单:在前面加上一句 USART1->SR;

具体代码如下:

USART1->SR;

USART_SendData(USART1, (uint8_t)ch);

while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);

下面我来说说原因: 第一句读取SR寄存器,第二句写DR寄存器 刚好清除了TC标志位 。第一次while循环就起作用了。

也可将USART1->SR;替换为USART_GetFlagStatus(USART1, USART_FLAG_TC)


推荐阅读

史海拾趣

Eclipse Magnetics公司的发展小趣事

由于篇幅限制,无法在此处直接提供5个完整的、每篇至少500字的Eclipse Magnetics公司电子行业发展的相关故事。不过,我可以概括地描述几个可能的故事线索,这些线索可以基于Eclipse Magnetics公司的历史、技术发展和市场应用来构建。

  1. 品牌初创与磁铁技术的突破

在1930年代,Eclipse Magnetics的名字首次出现,标志着这个品牌的诞生。随着技术的不断发展,公司在1940年代成为独立公司,并开始专注于磁铁技术的研发。到了1950年代,Eclipse Magnetics在技术上取得了重大突破,他们将磁铁涂上红色,并设计了与公司颜色相匹配的马蹄形标志,这一设计不仅提升了品牌形象,也成为了国际通用标记。这一时期的Eclipse Magnetics,以其独特的技术和产品,开始在电子行业中崭露头角。

  1. 航空航天领域的应用与拓展

随着航空航天技术的不断发展,Eclipse Magnetics看到了磁铁技术在该领域的巨大潜力。公司开始投入大量资源,研发适用于航空航天领域的磁性解决方案。通过不断的技术创新和产品优化,Eclipse Magnetics成功地为航空航天领域提供了高性能、高可靠性的磁铁产品,并在这一领域树立了良好的口碑。

  1. 与制药工业的深入合作

除了航空航天领域,Eclipse Magnetics还与制药工业建立了深入的合作关系。在制药过程中,磁铁技术可以用于磁选机,有效地去除原料中的杂质,提高药品的纯度。Eclipse Magnetics根据制药工业的特殊需求,定制了多款磁选机产品,并提供了全面的技术支持和售后服务。通过与制药工业的深入合作,Eclipse Magnetics不仅拓展了市场,也提升了自身的技术实力。

  1. 在汽车制造行业的应用

随着汽车制造业的快速发展,Eclipse Magnetics也看到了磁铁技术在该领域的广阔前景。公司针对汽车制造中的各个环节,研发了多款适用于不同场景的磁性解决方案。例如,在齿轮箱轴制造过程中,Eclipse Magnetics的磁性过滤器可以保持冷却液的清洁,提高生产效率和产品质量。这些解决方案不仅满足了汽车制造业的需求,也进一步巩固了Eclipse Magnetics在电子行业中的地位。

  1. 创新研发与可持续发展

作为一家专注于磁性技术的公司,Eclipse Magnetics始终将创新作为发展的核心动力。公司不断投入研发资源,推动磁铁技术的不断进步。同时,Eclipse Magnetics也关注可持续发展问题,致力于研发环保、高效的磁性产品。通过创新研发和可持续发展战略的实施,Eclipse Magnetics在电子行业中保持了领先地位,并为未来的发展奠定了坚实的基础。

请注意,以上内容仅为故事线索的概括描述,具体的故事细节和数据需要根据Eclipse Magnetics公司的实际情况进行补充和完善。

Corex Intervest Inc公司的发展小趣事

随着公司规模的不断扩大和市场竞争的加剧,Corex Intervest Inc公司意识到单打独斗已经无法满足市场需求。因此,公司开始积极寻求与其他企业的战略合作,共同推动电子行业的发展。公司与多家知名企业建立了战略合作关系,共同研发新产品、开拓新市场,实现了资源共享和互利共赢。

E-T-A [E-T-A Circuit Breakers]公司的发展小趣事

E-T-A公司的前身可以追溯到1948年,当时由Jakob Ellenberger和Harald A. Poensgen在德国共同创立了ELPO GmbH公司。这家初创企业专注于电气设备的研发和生产。随着技术的不断发展和市场的日益扩大,公司逐渐意识到设备用断路器在电路保护领域的重要性。因此,在1953年,公司正式推出了设备用的ETA断路器,并开始逐渐将重心转移到断路器领域,这也为日后E-T-A公司的成立奠定了基础。

Cardinal Components公司的发展小趣事

随着时间的推移,Cardinal不断推出新的产品系列以满足市场需求。2013年,公司推出了CJ速差器系列,这一系列产品以其高性能和稳定性受到了市场的广泛好评。随后,在2015年,CJ系列被移植到2.5×2.0封装尺寸,进一步提高了产品的集成度和可靠性。这些产品系列的拓展与升级不仅丰富了公司的产品线,也为客户提供了更多的选择。

迪一电子公司的发展小趣事

随着数字化和智能化技术的不断发展,迪一电子公司意识到必须跟上时代的步伐。于是,公司开始推进数字化转型和智能化生产。通过引入先进的生产设备和信息系统,优化生产流程,提高生产效率。同时,公司还注重人才培养和引进,建立了一支高素质的技术和管理团队。这些努力使迪一电子在数字化和智能化方面取得了显著成果,提高了公司的竞争力和市场地位。

General Semiconductor ( Vishay )公司的发展小趣事

Vishay一直致力于技术创新和产品升级。在2001年,公司收购了全球二极管和整流器领先制造商General Semiconductor,这一收购极大地增强了Vishay在二极管和整流器领域的实力。同时,Vishay还通过收购RFWaves公司,涉足无线领域,为公司带来了新的增长动力。此外,Vishay还在全球范围内布局制造基地和销售办事处,确保能够为客户提供优质的产品和服务。

问答坊 | AI 解惑

嵌入式系统与以太网的连接

1 引言   目前,以太网(Ethernet)协议已经非常广泛地应用于各种计算机网络,如办公局域网、工业控制网络等场合,并且还不断地发展。基于以太网的新技术和联网设备不断出现,以太网已经成为事实上最常用的局域网络标准之一。但是,基于以太网的 ...…

查看全部问答>

05年电子竞赛合集(一共有12篇哦)

本帖最后由 paulhyde 于 2014-9-15 08:56 编辑 希望大家会喜欢  …

查看全部问答>

脆求高手指点CoCreateInstance

各位高手:我在EVC下写了一个显示JPG图片的程序,可是在调用CoCreateInstance时总是失败,脆求高手指点啊! IImagingFactory *pImageFactory = NULL; IImage *pImage = NULL; CoInitializeEx(NULL,COINIT_MULTITHREADED); if(SUCCEEDED(CoCreat ...…

查看全部问答>

RaiseException 如何解决

各位好:我的平台基于WINCE5.0 上面有带CF 的WIFI.一旦无线网卡连接上网络,我打开Explorer 没有下面的错误信息出现。如果拔掉网卡,在打开EXPLORER 就会出现下面的信息,请问如何解决 谢谢 RaiseException: Thread=87647640 Proc=8299add0 \'ie ...…

查看全部问答>

mini gui和 qt比较 学习哪个好 现在哪个用的比较多 谢谢

我是初学   方向性问题  希望得到各位指点…

查看全部问答>

STM32有没可通过USB执行ISP的片子?

我觉得这种方式非常方便:一根USB、一台本本就可以去现场了。而且生产也方便!…

查看全部问答>

关于C调用汇编函数 参数问题

再看uC/OS-II移到msp430上时看到这里OSCPUSaveSR            MOV.W    SR,R12            DINT ...…

查看全部问答>

关于锂电池7.4V转5V的电源芯片

设计一个电路利用了7.4V的锂电池,但是工作电压为5v。这个电路的电流大约为150ma左右,应该用什么转换芯片呢?主要是考虑在锂电池正常工作的时候可以输出7.4V的电压,可是当电压下降之后如何保证输出为5V,因此想选一个输入电压范围比较宽的,有哪 ...…

查看全部问答>

MSP430 内置温度传感器的精度

产品说明书中提供了带有相应容差范围的额定 00C 电压与温度系数。额定 00C 电压规定为986mV,其最大误差为 +/- 5%。因此,温度传感器的 00C 电压在最恶劣的环境下,每个器件可能会相差几乎 +/- 50mV。这大约等于 +/- 14C。请注意,这种差异主要与各 ...…

查看全部问答>

有什么办法来检测MSP430是不是烧坏了。。。。

用5438A做AD试验的时候可能是电压过大,开发板的指示灯一下子就灭了。。。 然后就是下载不了了,想知道有没有什么办法确定是不是芯片烧了。。。。…

查看全部问答>