STM32学习之串口的使用

发布者:WanderlustHeart最新更新时间:2021-04-19 来源: eefocus关键字:STM32  串口  配置 手机看文章 扫描二维码
随时随地手机看文章

串口的使用 1、为什么要用串口?

自上一篇写的时间是1月20号,今6月7号了,半年没更新了。


这半年发生了什么?过完年就去找公司实习,在那里自我感觉进步很大。其实在公司大多都是自学,师傅基本不会给你说什么。但这并不能说明你的师傅对你不好,带我的那个师傅只比我高一届,但他的水平比我高的好多届。他也是自学,也没人告诉他该怎么做,因为老板也不太懂。所以自学能力很重要,当然有人带你的话,这样会更好。


不说这些了,串口在调试的时候作用非常大。也学我们在学51的时候,只是将程序下载到开发板,看看是否能运行起来,通过数码管将结果显示出来,从而就知道程序设计的正确性。以前我也是这样做的,没什么不好。


在公司实习的时候,他们调试都是使用串口打印输出信息,观察程序从上电、初始化、运行数据什么的全部都显示到PC机上。然后再一句一句分析它的打印信息,从而找到出错的源头。这使我对串口的认识有更深了一步,所以我决定在学习STM32的时候,开发流程跟在公司学的方法一样——使用串口,观察打印信息。


2、STM32跟PC机(也就是电脑)如何连接

我的STM32F103C8T6只是裸板,没有串口芯片,当然用的也是学生机——笔记本电脑,同样也没串口。


解决办法1、买一块 MAX3232转接板+一条USB转串口线 +邮费=30块左右


2、只需要买一块PL2303的USB转接板。这样就将第一种的转接板和连接结合到一起了。


不过我用的是第一种,MAX3232+USB的串口线,为什么不用方便的2种?


max3232对于没有串口的开发板可以充当电平转换芯片,如何开发板有了电平转换芯片,我便使用USB转串口线经行连接,这样便灵活了。第二种只是用在既没转换芯片也没USB转串口的情况,不过对于最小系统板来说,它既可以下载程序,又可以当做串口来调试。至于台式机就不需要USB转串口线了,普通串口线即可。


连接示意如下所示:


3、代码分析

再写这里之前,应该已经学过模块化编程了,STM32的每个XXX.c 和xxx.h 这都是模块化编程。良好的程序,与其好的代码风格有关。你的代码风格跟你接触教你写代码的有很大关系。以前刚刚学习单片机编程,我还不信,现在我承认,跟教我单片机的老师风格有些像。


这里我做的是一个串口发送数据到PC机的例子:


要让STM32能够顺利发出数据,要进行如下配置


PA9,PA10管脚要配置,USART也需要配置波特率,数据有几位,停止位,数据流等。


USART和uart有什么区别USART在做串口时,两者并不区别,但是USART有SPI的功能。还有串口通信为什么要配置波特率,停止位,硬件数据留这些,以前我也没想过,现在只觉得协议这个东西,是一个好的标准。


建立一个usart_debug.c的文本,内容如下


#include"usart_debug.h"


void GPIO_Configuration(void)


{


GPIO_InitTypeDefGPIO_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能UASRT的时钟


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA的时钟,开始的时候,我没用这句话,调了两天,跟源码一句一句比才知道


RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);


GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;


GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //波特率较高,IO翻转需较高频率


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;我看网上有人说设置成GPIO_Mode_Out_PP普通推挽输出也行,但实践出真知,我试了发送是乱码。;


GPIO_Init(GPIOA,&GPIO_InitStructure);




GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //配置成浮空输入,既然是输入所以就不用配置IO口的频率了


GPIO_Init(GPIOA,&GPIO_InitStructure);


}




void USART1_config(void)


{


USART_InitTypeDefUSART_InitStructure;


USART_InitStructure.USART_BaudRate= 115200;//配置波特率


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(USART1, &USART_InitStructure);




USART_Cmd(USART1, ENABLE);


}


//这段很重要,如果要使用printf函数打印信息,需要加fputc函数,就需要对printf函数重定向到串口,以前工作中他们老是提重定向,什么串口重定向,USB重定向什么的,我也是云里雾里,如今给我的感觉就是将上层函数实现对底层硬件的操作


intfputc(int ch,FILE*f){


while(USART_GetFlagStatus(USART1, USART_FLAG_TC) !=SET); //网上的一些函数里面是没有这一句代码,如果不加的话,打印时第一个字符就会没有,原因据说是硬件复位后,USART_FLAG_TC被置一了,而要发送数据必须让其为底才可以,一表示数据发送发出的标志,也可以用这样一句USART_ClearFlag(USART2,USART_FLAG_TC);清楚标准位。可是我没这样做一样发成功了,这个疑惑以后再想明白。


USART_SendData(USART1, (uint16_t)ch);




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


return ch;




}


void usart_debug_config(void)//提供给main函数调用的串口配置函数


{


GPIO_Configuration(); //IO口配置


USART1_config();//串口配置


}






还就是usart_debug.h


#ifndef __usart_debug_H


#define__usart_debug_H




#include "stm32f10x.h"


#include




void usart_debug_config(void);


int fputc(int ch, FILE *f);






#endif// __USART1_H












main函数:


这里使用两种方式一种是 使用普通的方式发送,另一种使用printf函数


其实还有一种USART_printf函数来实现,这里不做介绍。有空看看区别一下printf和usart_printf,据说是支持格式多少的问题




#include"stm32f10x.h"


#include"usart_debug.h" //包含main函数里的调用函数


int main(void)


{




unsigned char TxBuf1[100] ={"发送字符串!!!rn"};


inti;


SystemInit();


usart_debug_config();


for( i = 0; TxBuf1[i] != ''; i++)


{


while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);//这里跟分析fputc时是一样的


USART_SendData(USART1 , TxBuf1[i]);//发送字符数组里的单个字符


while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);


}




printf("hello world!世界你好! rn"); //调用printf函数


while(1)


{


;


}




}





仿真及调试

程序编好之后,在target option里要选择 USE microLIB (keil自带的微库),这是使用非标准C库,在编译链接是,将我们编写的fputc函数作为编译的首选,否则就会编译stdio.h里的fputc函数。


写到这里我发现我这个代码感觉不是很好,使用微库而不用标准C库,应该会有影响,我瞬间就明白了他们为什么要自己编写支持输出格式很少的的USART_printf函数了,后面目测我也会使用这个函数。


一个好的程序代码就是结构健全,BUG很少。把简单做到极致




在KEIL里继续软件仿真


仿真和下载时要注意的是,仿真要选USE Simulation而下载要选右边的JTAG。。。。



然后点击debug 进入调试界面




view--->serial windos -->UART 1


全速运行 其结果如下:



串口发送数据就到此为止。

串口接收数据

这儿写的跟上面的已经没有关系了,不要搞混。


关于从PC机发送数据到STM32,这一部分则需要中断来实现,因为我们不需要时时刻刻都来检测外部是否发出数据给STM32,因此只要有数据来,就触发中断。这里就需要配置NVIC了


void NVIC_Config(void)


{


NVIC_InitTypeDef NVIC_InitStructure;




NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //优先组为2


NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//打开USART中断通道


NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级


NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级


NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断通道使能


NVIC_Init(&NVIC_InitStructure);




USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//串口接收中断使能




USART_Cmd(USART1, ENABLE);


}






其他配置比如串口复用到IO配置,串口时钟配置,和发送数据是一样的。






串口中断处理函数:






void USART1_IRQHandler(void)


{int RX_status;//自己定义一个标志位


RX_status = USART_GetFlagStatus(USART1, USART_FLAG_RXNE);//读取接收数据标志位,如果装好了一帧数据则硬件将其置一。


if(RX_status == SET) {


USART_SendData(USART1 , USART_ReceiveData(USART1));//将收到的数据再由STM32发送给PC机。


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




}


}


串口的发送接收大致如此,还是要搞懂什么数据位,硬件流,停止位,校验位什么,一个东西既然出现了就要好好分析出现的意义。想到了今天给电脑拆机清灰,电脑最好两年清一次。反正每次上螺丝都会多出那么一两个来,是不是可以不用要?


肯定不是,生产商肯定也知道节约成本什么,他们的结构工程师也知道PCB上开一个螺丝孔也是要收钱的。所以每一颗螺丝都有它的意义,所以什么校验位,停止位也有他的意义,即便我们不使用。其实剩的螺丝我也扔了,完全不知道上在哪儿!


关键字:STM32  串口  配置 引用地址:STM32学习之串口的使用

上一篇:STM32 无中断串口代码
下一篇:STM32高级定时器1控制伺服直流电机

推荐阅读最新更新时间:2024-11-09 14:24

STM32标准外设库SPL转换成 Cube LL
今天分享几点内容: 1.介绍ST推出的三种库; 2.直接操作寄存器及三种ST库的代码性能对比; 3.STM32CubeMX直接生成Cube LL库函数的方法; 4.STM32标准外设库SPL转换成Cube LL的方法; 1介绍ST推出的三种库 1.标准外设库:Standard Peripheral Libraries,简写SPL. 2.Cube硬件抽象层库:STM32Cube Hardware Abstraction Layer,简写Cube HAL. 3.Cube底层库:STM32Cube Low-Layer,简写Cube LL. 开发STM32常见的除了直接读写(操作)寄存器之外,就是使用ST推出的库函数进行开发。 这三种库中
[单片机]
<font color='red'>STM32</font>标准外设库SPL转换成 Cube LL
不用串口,如何打印STM32单片机log
本文主要介绍在嵌入式开发中用来输出log的方法。 最常用的是通过串口输出uart log,这种方法实现简单,大部分嵌入式芯片都有串口功能。但是这样简单的功能有时候却不是那么好用,比如: 一款新拿到的芯片,没有串口驱动时如何打印log 某些应用下对时序要求比较高,串口输出log占用时间太长怎么办?比如USB枚举。 某些bug正常运行时会出现,当打开串口log时又不再复现怎么办 一些封装中没有串口,或者串口已经被用作其他用途,要如何输出log 下文来讨论这些问题。 1输出log信息到SRAM 准确来说这里并不是输出log,而是以一种方式不使用串口就可以看到log。在芯片开发阶段都可以连接仿真器调试,可以使用打断点的方法调试,但是有
[单片机]
不用<font color='red'>串口</font>,如何打印<font color='red'>STM32</font>单片机log
vivo X80 Pro影像配置解密:5000万像素GNV主摄
IT之家 4 月 19 日消息,vivo X80 系列新品发布会将于 4 月 25 日 19:00 举行,今天博主 @数码闲聊站 曝光了 vivo X80 Pro 影像系统的详细配置。   据该博主透露,vivo X80 Pro 搭载 50MP 三星 GNV 1/1.3“f / 1.57 主摄 + 48MP IMX598 1/2” 超广角 + 12MP IMX663 1/2.9“ 2X 微云台人像 + 8MP Hi847 5X 潜望超长焦,其它还有 vivo 自研的 V1 + 影像芯片、G+P 玻塑镜头和蔡司 T * 镀膜。   据悉,三星 GNV 超大底主摄是三星 GN1 的定制小升级版本。   该博主还透露,三季度 v
[手机便携]
Keil MDK STM32系列(十) Ubuntu下的PlatformIO开发环境
这篇和Keil MDK没什么关系, 但是HAL库和开发方式是一样的, 也放在这个系列下吧 PlatformIO PlatformIO是VSCode的一个扩展, 主要面向的是嵌入式的开发, 因为VSCode的跨平台属性, PlatformIO也是跨平台的. 这里主要介绍在Ubuntu20.04下的PlatformIO环境. 安装, 略 PlatformIO下的STM32烧录工具 对于STM32, PlatformIO支持的烧录工具有 blackmagic, cmsis-dap, dfu, jlink, serial, stlink, 直接选stlink就可以了. PlatformIO下的STM32封装库 在Platf
[单片机]
STM32 ILI9341驱动TFTLCD(七)LCD画实心三角形、矩形、圆形
上次测试画直线函数时,已经通过三条直线画出了一个空心三角形,今天来画一下实心的,分别画下实心三角形、实心矩形、实心圆。 1、实心三角形 实心三角形,可以先画任意两条边,然后以这两条边的交点为顶点,向第三条直线的点画直线。在画第三条直线时,思想和画直线是一样的,只是在画好点之后,多加了顶点向刚画好的点画直线这一步。到第三条直线画完时,实心三角形也就画好了。 画实心三角形函数 void LCD_DrawSolidTriangle(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2,u16 color) { u16 xm = 0,ym = 0; u16 step = 0; L
[单片机]
<font color='red'>STM32</font> ILI9341驱动TFTLCD(七)LCD画实心三角形、矩形、圆形
STM32如何通过FSMC点亮LCD
FSMC是Flexible static memory controller(可变静态存储控制器)的简称,是STM32系列采用的一种新型的存储器扩展技术,支持SRAM、Nor Flash、LCD、PSRAM、NAND Flash、PC Card等。只在某些芯片上有,使用前要查看对应的手册确定。 在FSMC的角度来看,外部存储分成了4个固定的大小为256MB的bank。 Bank1分成了4个子bank,每一个64MB大小,并且每个bank都有独立的片选,用来控制Nor Flash、RAM、PSRAM。Bank2和Bank3用来控制NAND Flash。Bank4控制PC Card。 不同的Bank共享了地址、数据、读、写
[单片机]
<font color='red'>STM32</font>如何通过FSMC点亮LCD
MPU6050的四元数解算姿态方法
 最近在研究小四轴的飞行,姿态检测主要用到的传感器是MPU6050。从MPU6050读出来的加速度和角速度数据最后要转成姿态,可以转换成欧拉角(偏航角、俯仰角和滚转角)或四元数表示,为了减少计算量(欧拉角涉及正弦运算,运算量相对较大),方便在STM32主控上实现,可以转换成四元数表示。   使用MPU6050硬件DMP解算姿态是非常简单的,下面介绍由三轴陀螺仪和加速度计的值来使用四元数软件解算姿态的方法。   我们先来看看如何用欧拉角描述一次平面旋转(坐标变换):      设坐标系绕旋转α角后得到坐标系,在空间中有一个矢量在坐标系中的投影为,在内的投影为由于旋转绕进行,所以Z坐标未变,即有。      转换成矩阵形式
[单片机]
MPU6050的四元数解算姿态方法
STM32固件库
很久没有碰单片机了,两年了吧,因为项目需要,最近入手一块红牛的开发板,核心为STM32F103ZE。虽然以前做过大概半年的stm32的开发,现在天天在.net平台下写代码,已经忘记的差不多,恰逢周末,补补课,以后用的时候也方便点。 ST推出的FW大大提高了单片机SW的开发效率,所以在新建工程前先来了解下这个SDK。我使用的是最新的v3.5固件库,这个固件库可以分为三个部分: 1、内核支持(..STM32F10x_StdPeriph_Lib_V3.5.0LibrariesCMSISCM3CoreSupport) 2、硬件系统支持(..STM32F10x_StdPeriph_Lib_V3.5.0LibrariesCMSI
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved