失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 《STM32从零开始学习历程》——USART串口通讯实验篇2——指令控制LED灯实验

《STM32从零开始学习历程》——USART串口通讯实验篇2——指令控制LED灯实验

时间:2021-05-31 21:16:12

相关推荐

《STM32从零开始学习历程》——USART串口通讯实验篇2——指令控制LED灯实验

《STM32从零开始学习历程》@EnzoReventon

USART串口通讯实验篇2——指令控制LED灯实验

本实验是在《USART串口通讯实验篇1——中断接收与发送》的基础上完成的,可以先学习实验1,然后再进行此实验,如果实验1能够理解并且处理的游刃有余,那么实验2将是小菜一碟了,本着从零开始的目的,我们还是一步一步,讲的详细一些。

1. 实验准备

软件:Keil μVision5 v5.33(MDK5),串口助手XCOM V2.6

环境:Windows10 Enterprise x64

芯片:STM32F406ZGT6

设备:正点原子STM32F4探索者开发板

仿真器:ST-Link

参考手册

[野火EmbedFire]《STM32库开发实战指南——基于野火霸天虎开发板》

[正点原子]STM32F4开发指南-库函数版本_V1.2

[ST]《STM32F4xx中文参考手册》

[ST]《STM32F407xx》

2. 实现功能

通过串口助手向STM32发送特定的指令,实现对LED灯的控制。

如:

发送字符“1”-----》LED1亮

发送字符“2”-----》LED2亮

发送字符“3”-----》LED1&LED2亮

发送字符“4”-----》LED1灭

发送字符“5”-----》LED2灭

发送字符“6”-----》LED1&LED2灭

3. 硬件设计流程

查阅开发板手册以及芯片手册非常重要!

根据实验1《USART串口通讯实验篇1——中断接收与发送》配置好USART通讯串口,本实验中,仍然使用USART1 PB6\PB7引脚。查阅“正点原子”探索者F4开发板硬件电路,找到LED灯所对应的引脚。

小结:由硬件连接图与电路设计图可以看出,LED1与LED2连接于芯片的PF9与PF10端口,在软件设计时需要对这两个GPIO进行初始化设置。

由电路设计图可以看出,如果PF9与PF10端口为高电平(3.3V),则没有电压流过LED灯管,只有当PF9与PF10为低电平时才有电流流过LED灯管,因此只有使用GPIO_ResetBits()函数才可以点亮LED。

4. 程序设计流程

串口初始化时钟使能:RCC_APBxPeriphClockCmd();

GPIO初始化时钟使能:RCC_AHBxPeriphClockCmd();引脚复用映射:GPIO_PinAFConfig();GPIO端口模式配置:GPIO_Init();串口参数初始化:USART_Init();串口使能:USART_Cmd();重定向printf与scanf函数;LED初始化:LED_Init();

5. 代码设计与分析

本实验设计分为三个部分:USART初始化子函数、LED初始化子函数,主函数。

1. 初始化USART

初始化USART串口函数:

void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;//定义初始化结构体变量USART_InitTypeDef USART_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟//串口1对应引脚复用映射GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_USART1); //GPIOB6复用为USART1GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1);//GPIOB7复用为USART1//USART1端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //GPIOB6与GPIOB7GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化PB6,PB7//USART1 初始化设置USART_InitStructure.USART_BaudRate = bound;//波特率设置USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式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); //初始化串口1USART_Cmd(USART1, ENABLE); //使能串口1 }

重定向c库函数printf到串口,重定向后可使用printf函数:

在进行重定向函数编写时首先需要完成如下两个操作:

(1)在MDK5界面中点击“”图标,将“USE MicroLIB”打上勾勾。

(2)在定义文件中需要包含#include “stdio.h”头文件。

int fputc(int ch , FILE *f){USART_SendData(USART1,(uint8_t) ch );while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);//USART_FLAG_TXE:发送数据寄存器中的数据有没有被取走return (ch);}

重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数:

int fgetc(FILE *f){while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);//USART_FLAG_TXE:发送数据寄存器中的数据有没有被取走return (int)USART_ReceiveData(USART1);}

关于重定向函数的一些解释:

对于上文重定向printf、scanf与getchar函数读者可能对此有疑惑,故在此做一下说明。

重定向

就是指重新定义C库函数。对于printf()函数而言,printf只是一个宏定义,实际上调用的是fputc()函数,为了能够使用printf()函数直接向串口发送数据,需要重定向fputc()函数。同理,重定向scanf()函数也是这个意思。

FILE *f是单片机函数重定向的固定用法,因为C语言和单片机对fputc(),fgetc()函数的定义是不同的,在C中,标准的参数为int xxx , FILE *x,如果没有FILE *x 这个指针变量,则无法实现重定向,因此这是一个固定用法。

在定义函数时,FILE *x 这个指针变量必须有,但是函数主体中可以不使用。

2. 初始化LED

void LED_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟//GPIOF9,GPIOF10初始化设置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0和LED1对应IO口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIOGPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10设置高,灯灭}

3. 主函数

对于主函数的编写比较清晰,先对串口、LED进行初始化调用,然后使用Switch对串口接收到的信息进行匹配,从而执行相应的动作。

此外还可以额外定义一个全局函数Show_Message()用来向串口发送提示信息。

static void Show_Message(void);//函数申明int main(void){char ch;//开辟一个字符存储空间delay_init(168);//延时初始化 uart_init(115200);//串口初始化波特率为115200LED_Init(); //初始化与LED连接的硬件接口 Show_Message();//显示提示信息while(1){ch = getchar();if(ch != '\0'){printf("接收到字符:%c\n",ch);}switch(ch){case '1':GPIO_ResetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.9拉低,亮 ,等同LED0=0;break;case '2':GPIO_ResetBits(GPIOF,GPIO_Pin_10); break;case '3':GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);break;case '4':GPIO_SetBits(GPIOF,GPIO_Pin_9);break;case '5':GPIO_SetBits(GPIOF,GPIO_Pin_10);break;case '6':GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);break;default:Show_Message();break;}}}static void Show_Message(void)//定义全局函数{printf("\n 串口通讯控制实验: \n");printf("指令 ----------- 跑马灯\n");printf(" 1 ----------- LED1 ON \n");printf(" 2 ----------- LED2 ON \n");printf(" 3 ----------- LED1&2 ON \n");printf(" 4 ----------- LED1 OFF \n");printf(" 5 ----------- LED2 OFF \n");printf(" 6 ----------- LED1&2 OFF \n");}

6. 调试

编译,下载程序。

使用XCOM串口调试助手,会发现接收框不断地有Show_Message()中编写的提示信息发送过来。

在发送框中,输入3,点击发送。如下图所示,LED1&0被点亮,串口接收到指令3。

至此,试验结束。

7. 小结

其实本实验不难,是基于实验1进行了一些小改动而来的,主要是要了解下重定向。

有了此实验的基础,对于后期的实验或者工程会有很大的帮助。

如有不足之处还请各位大佬及时指出!

如果觉得《《STM32从零开始学习历程》——USART串口通讯实验篇2——指令控制LED灯实验》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。