1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
USART串口通讯实验篇2——指令控制LED灯实验 本实验是在《USART串口通讯实验篇1——中断接收与发送》的基础上完成的,可以先学习实验1,然后再进行此实验,如果实验1能够理解并且处理的游刃有余,那么实验2将是小菜一碟了,本着从零开始的目的,我们还是一步一步,讲的详细一些。 1. 实验准备 软件:Keil μVision5 v5.33(MDK5),串口助手XCOM V2.6 环境:Windows10 Enterprise x64 芯片:STM32F406ZGT6 设备:正点原子STM32F4探索者开发板 仿真器:ST-Link 2. 实现功能 通过串口助手向STM32发送特定的指令,实现对LED灯的控制。 如: 发送字符“1”-----》LED1亮 发送字符“2”-----》LED2亮 发送字符“3”-----》LED1&LED2亮 发送字符“4”-----》LED1灭 发送字符“5”-----》LED2灭 发送字符“6”-----》LED1&LED2灭 3. 硬件设计流程 查阅开发板手册以及芯片手册非常重要!
小结:由硬件连接图与电路设计图可以看出,LED1与LED2连接于芯片的PF9与PF10端口,在软件设计时需要对这两个GPIO进行初始化设置。 由电路设计图可以看出,如果PF9与PF10端口为高电平(3.3V),则没有电压流过LED灯管,只有当PF9与PF10为低电平时才有电流流过LED灯管,因此只有使用GPIO_ResetBits()函数才可以点亮LED。 4. 程序设计流程
本实验设计分为三个部分: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复用为USART1 GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1); //GPIOB7复用为USART1 //USART1端口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //GPIOB6与GPIOB7 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_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); //初始化串口1 USART_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; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOF, &GPIO_InitStructure); //初始化GPIO GPIO_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); //串口初始化波特率为115200 LED_Init(); //初始化与LED连接的硬件接口 Show_Message(); //显示提示信息 while(1) { ch = getchar(); if(ch != ' |