STM32串口通信之超级终端控制LED灯

发布者:Jinyu521最新更新时间:2019-03-09 来源: eefocus关键字:STM32  串口通信  超级终端控制  LED灯 手机看文章 扫描二维码
随时随地手机看文章

一、硬件介绍


本程序使用开发板:STM32-PZ6806L


1、GPIO控制LED


开发板中LED的硬件电路参看:直接通过寄存器地址操作控制LED灯


2、串口


开发板中连接了MCU的2个串口,分别为USART1和USART3,其中USART1通过CH340G接PC端USB口,实现USB转串口功能,可以用于程序下载和串口通信,但通过PC端的超级终端连接时不能连接,所以本程序使用开发板上的另一个串口USART3,该串口信号转换成RS232,通过直连串口线与PC端的COM口相连,可以实现与超级终端通信。


开发板串口的硬件连接图请参考:STM32串口通信之Hello


二、项目创建与配置


请参看《STM32串口通信之Hello》中的“使用库函数的串口程序项目配置”,在此基础上,在"User"文件夹下新建"Led"文件夹,并将该文件夹配置在"C/C++"选项卡中的"Include Paths"包含文件路径中。


三、LED灯控制


1、新建"Led.h"文件并保存在"User/Led"文件夹下,内容如下:


#ifndef __LED__H


#define __LED__H


#include "stm32f10x.h"


#define LED_PORT     GPIOC


#define LED_PIN        (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7)


#define LED_PORT_RCC RCC_APB2Periph_GPIOC


#define LED1 GPIO_Pin_0


#define LED2 GPIO_Pin_1


#define LED3 GPIO_Pin_2


#define LED4 GPIO_Pin_3


#define LED5 GPIO_Pin_4


#define LED6 GPIO_Pin_5


#define LED7 GPIO_Pin_6


#define LED8 GPIO_Pin_7


 


void LED_Init(void);


void LED_On(u8 x, u8 en);


#endif


2、新建"Led.c"文件并保存在"User/Led"文件夹下,内容如下:


#include "led.h"


void LED_Init()


{


         GPIO_InitTypeDef GPIOC_0_mode;


         RCC_APB2PeriphClockCmd( LED_PORT_RCC, ENABLE );           //使能GPIOC时钟


         GPIOC_0_mode.GPIO_Pin = LED_PIN;


         GPIOC_0_mode.GPIO_Speed = GPIO_Speed_50MHz;


         GPIOC_0_mode.GPIO_Mode = GPIO_Mode_Out_PP;


         GPIO_Init(GPIOC, &GPIOC_0_mode);


}


void LED_On(u8 x, u8 en)


{


         uint16_t led[] = {LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8};


         if(x


                   return;


         if(en=='y')


                   GPIO_ResetBits(LED_PORT,led[x-0x31]);


         else


                   GPIO_SetBits(LED_PORT,led[x-0x31]);


}


LED_Init函数使能GPIOC时钟,设置GPIOC_0~GPIOC_7为推挽输出模式,LED_On函数根据参数x和en来设置单个LED灯的亮灭状态,调用函数GPIO_ResetBits来复位管脚,即点亮LED灯,调用函数GPIO_SetBits来置位管脚,即灭LED灯。x参数为第几个LED灯的数字字符,en参数为'y'字符或'n'字符,'y'表示点亮,'n'表示灭灯。


四、串口通信程序


该串口通信采用USART3,发送数据采用查询方式,接收数据采用中断方式,所以需要使能GPIOB和USART3时钟、配置中断、配置USART3、使能中断和使能USART3等操作。


1、创建"usrt.h"文件并保存在"User/Uart"文件夹下,内容为:


#ifndef __UART__H


#define __UART__H


#include "stm32f10x.h"


#include "stdarg.h"


#include "stdlib.h"


#include "string.h"


#include "stdio.h"        


#define EN_USART1 0         //禁用USART1


#define EN_USART3 1         //启用USART3


 


#define USART_n                 USART3    //使用USART3用于fputc


 


#define USART1_REC_LEN                          200 


extern u8  USART1_RX_BUF[USART1_REC_LEN];


extern u16 USART1_RX_STA;  


 


#define USART3_REC_LEN                          200 


extern u8  USART3_RX_BUF[USART3_REC_LEN];


extern u16 USART3_RX_STA;  


 


void USART1_Config(u32 baud);


void USART1_printf(char* fmt,...);


 


void USART3_Config(u32 baud);


void USART3_printf(char* fmt,...);


#endif


2、创建"usrt.c"文件并保存在"User/Uart"文件夹下,内容为:


#include "uart.h"


 


//重写fputc函数


int fputc(int ch, FILE *f){      


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


  USART_SendData(USART_n, (unsigned char)ch);     


         return ch;


}


 


#if EN_USART1


u8 USART1_RX_BUF[USART1_REC_LEN];     //接收缓冲区,最大USART_REC_LEN个字节.


//接收标志


//bit15,        置位表示接受完成


//bit14,        置位表示接收到0x0d


//bit13~0,   接收字符个数


u16 USART1_RX_STA=0;       //16位接收记录标志全局变量 


void USART1_Config(u32 baud)


{


         GPIO_InitTypeDef GPIO_InitStructure;


         USART_InitTypeDef USART_InitStructure;


         NVIC_InitTypeDef NVIC_InitStructure;


         //Enable GPIOA and USART1


         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);


         //Config GPIOA_9 and GPIOA_10


         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;


         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;


         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


         GPIO_Init(GPIOA, &GPIO_InitStructure);


        


         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;


         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;


         GPIO_Init(GPIOA, &GPIO_InitStructure);


         //USART1 NVIC config


         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //配置NVIC中断分组2:2位抢占,2位响应


         NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;


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


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


         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                            //IRQ通道使能


         NVIC_Init(&NVIC_InitStructure);          //初始化NVIC寄存器


         //Config USART1


         USART_InitStructure.USART_BaudRate = baud;


         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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//使能USART1的接收中断


         //Enable USART1


         USART_Cmd(USART1, ENABLE);


}


 


void USART1_IRQHandler(void){ //USART1中断函数 


         u8 Res;


         //(USART1_RX_STA&0x3FFF)为数据的长度(不包括回车符)


         //当(USART1_RX_STA&0xC000)为真时表示数据接收完成(超级终端按下回车键),


         //读到0x0d 0x0a表示数据结束


         //在main函数中处理完接收数据后将USART_RX_STA置0


                   printf("a");


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


         {    


                   Res =USART_ReceiveData(USART1);//接收一个字符


                   printf("%c",Res); //会送给PC


                   if((USART1_RX_STA & 0x8000)==0)            //本次接收未完成


                   {                                  


                            if(USART1_RX_STA & 0x4000)                     //已经接收到了0x0d


                            {                                                              


                                     if(Res!=0x0a)      //如果已经接收了回车符,而本次接收的不是换行符,则数据出错


                                               USART1_RX_STA = 0;       


                                     else


                                               USART1_RX_STA |= 0x8000;      //标记数据接收完成


                            }


                            else   //没有接收过0X0D表示为信息字符


                            {                                 


                                     if(Res==0x0d)    //本次接收是0x0d,则在USART1_RX_STA中标记


                                               USART1_RX_STA |= 0x4000;


                                     else   //本次接收不是0x0d,则确定是信息字符,存入数组中


                                     {


                                               USART1_RX_BUF[USART1_RX_STA & 0X3FFF]=Res ; //字符存入数组中


                                               USART1_RX_STA++;         //数据长度加1


                                               if(USART1_RX_STA > (USART1_REC_LEN-1))   //如果数据长度超过缓冲区大小,出错,重新接收


                                                        USART1_RX_STA=0;


                                     }                


                            }


                   }               


         }


}


#endif


 


#if EN_USART3


u8 USART3_RX_BUF[USART3_REC_LEN];     //接收缓冲区,最大USART_REC_LEN个字节.


//接收标志


//bit15,        置位表示接受完成


//bit14,        置位表示接收到0x0d


//bit13~0,   接收字符个数


u16 USART3_RX_STA=0;       //16位接收记录标志全局变量 


void USART3_Config(u32 baud)   //初始化UASRT3


{


  //GPIO端口设置


  GPIO_InitTypeDef GPIO_InitStructure;


         USART_InitTypeDef USART_InitStructure;


         NVIC_InitTypeDef NVIC_InitStructure;


                    


         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); //使能UART3对应的GPIOB


         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能串口的RCC时钟


 


         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //配置USART3的RX引脚PB11


         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入


         GPIO_Init(GPIOB, &GPIO_InitStructure);


 


         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置USART3的TX引脚PB10


         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         //服用推挽输出


         GPIO_Init(GPIOB, &GPIO_InitStructure); 


 


   //Usart3 NVIC 配置


         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;


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


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


         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                            //IRQ通道使能


         NVIC_Init(&NVIC_InitStructure);          //初始化NVIC


   //USART3 初始化设置


         USART_InitStructure.USART_BaudRate = baud;//波特率;


         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(USART3, &USART_InitStructure); //初始化串口


         USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//使能接收中断


         USART_Cmd(USART3, ENABLE);                    //使能串口


}


 


void USART3_IRQHandler(void)  //USART3中断函数


{     


         //(USART1_RX_STA&0x3FFF)为数据的长度(不包括回车符)


         //当(USART1_RX_STA&0xC000)为真时表示数据接收完成(超级终端按下回车键),


         //读到0x0d 0x0a表示数据结束


         //在main函数中处理完接收数据后将USART_RX_STA置0


         u8 Res;


         //       printf("a");


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


         {    


                   Res =USART_ReceiveData(USART3);//接收一个字符


                   printf("%c",Res); //回送给PC


                   if((USART3_RX_STA & 0x8000)==0)            //本次接收未完成


                   {                                  


                            if(USART3_RX_STA & 0x4000)                     //已经接收到了0x0d


                            {                                                              


                                     if(Res!=0x0a)      //如果已经接收了回车符,而本次接收的不是换行符,则数据出错


                                               USART3_RX_STA = 0;       


                                     else


                                               USART3_RX_STA |= 0x8000;      //标记数据接收完成


                            }


                            else   //没有接收过0X0D表示为信息字符


                            {                                 


                                     if(Res==0x0d)    //本次接收是0x0d,则在USART1_RX_STA中标记


                                               USART3_RX_STA |= 0x4000;


                                     else   //本次接收不是0x0d,则确定是信息字符,存入数组中


                                     {


                                               USART3_RX_BUF[USART3_RX_STA & 0X3FFF]=Res ; //字符存入数组中


                                               USART3_RX_STA++;         //数据长度加1


                                               if(USART3_RX_STA > (USART3_REC_LEN-1))   //如果数据长度超过缓冲区大小,出错,重新接收


                                                        USART3_RX_STA=0;


                                     }                


                            }


                   }               


         }


}


#endif


3、"main.c"程序


#include "uart.h"


#include "led.h"


int main()


{


         u8 ch1, ch2, i;


         LED_Init();//LED GPIO初始配置


         USART3_Config(115200); //USART1配置,接收中断


         USART3_RX_STA = 0xC000; //数据初始为接收回车状态


         for(i=0;i<8;i++)  //将8个LED初始设为灭灯状态


                   LED_On(i+0x31,'n');


         while(1)


         {


                   if(USART3_RX_STA & 0xC000)//接收到回车-0xC000


                   {


                            if((USART3_RX_STA & 0x3FFF)==0) //数据长度为0,显示菜单


                            {


                                     printf("\033[1;47;33m\r\n"); //设置超级终端文字颜色


                                     printf(" xy--开LEDx灯     xn--灭LEDx灯 \r\n");


                                     printf(" 请输入控制指令,按回车键执行! \033[0m\r\n");


                            }


                            else if((USART3_RX_STA&0x3FFF)==2)


                            {


                                     ch1 = USART3_RX_BUF[0];


                                     ch2 = USART3_RX_BUF[1];


                                     if(      ch1>='1' && ch1<='8'&&( ch2=='y' || ch2=='n'))


                                     {


                                               LED_On(ch1, ch2);


                                               printf("LED%c%s\r\n",ch1,ch2=='y'?"开了":"关了");


                                     }


                                     else


                                               printf("命令错误\r\n");


                            }


                            USART3_RX_STA = 0; //完成一次操作,复位


                   }


         }


}


在此程序中分别对USART1和USART3实现了同样的操作,这里实际用到的是USART3,本程序参考杜洋老师的程序实现。


五、项目编译、开发板设置及程序运行


1、在项目的"User"组中加入"led.c"和"uart.c"文件,编译,连接生成.hex文件;


2、将开发板中的P232的两个跳线帽连接到COM3;


3、将程序下载到开发板;


4、在PC机上运行"HyperTerminal"程序,新建连接:


HyperTerminal运行如下:

超级终端上的显示与开发板上LED灯的状态一致。


关键字:STM32  串口通信  超级终端控制  LED灯 引用地址:STM32串口通信之超级终端控制LED灯

上一篇:成功移植icore的shell串口到STM32F4
下一篇:使用STM32固件库函数操作控制LED灯

推荐阅读最新更新时间:2024-03-16 16:25

stm32中AT发送可变短信
/******************** (C) COPYRIGHT 2015 ************************** * 文件名 :main.c * 描述 :使用方法: p为要发送的短信内容 * center为手机卡的短信中心 * tel为要发送的手机号的号码 * 串口会打印AT操作的内容 **********************************************************************************/ #include stm32f10x.h #include usart1.h #include wchar.h #include wc
[单片机]
STM32使用ADC功能
1.关于ADC输入通道与GPIO口的输入关系需要查看STM32芯片手册(p31)而非数据手册。 2.外部触发源指的是触发ADC采样的触发信号,这与1的GPIO口输入是两个不同概念。而JEXTBEL 或者EXTBEL 决定具体是哪个触发源。 3.大的方向,触发模式分为了 ADON位触发启动和外部触发启动ADC转换两种。用后者就行了 4.当我们使用一个ADC要采集多个通道时,单独规则组由于只使用了一个数据寄存器,并且是整个组转换完后才会触发中断,因此数据会覆盖,这种情况下需要使用DMA方法(后面采用试试),这时数据写到SRAM中了。而单独使用注入组总共可最多有四个通道,对应四个数据寄存器,不存在覆盖。 5.关于注入通道
[单片机]
<font color='red'>STM32</font>使用ADC功能
成本低、易于编程控制的DLP投影STM32单片机驱动电路研究设计
DLP投影技术是应用美国德州仪器公司开发的数字微镜元件--DMD(Digital Micromirror Device)作为主要关键处理元件以实现数字光学处理过程的技术。DLP显示的色彩清晰度高、艳丽、细腻、逼真,且为全数字显示即可靠性极高,能在各类产品(如大屏幕数字电视、公司/家庭/专业会议投影机和数码相机(DLP Cinema))中提供最佳图像效果。目前,大部分的家用或商用DLP投影机都采用了单片结构,使得其便于移动携带,因而得到越来越广泛的应用。在目前应用发展的基础上,又对其结构的精简性、携带的方便性提出了更高的要求。传统的DLP投影仪是通过DVI接口接收外部信号,并且经过信号转换传送给DLP控制器来控制DLP的显示,占用的
[单片机]
成本低、易于编程<font color='red'>控制</font>的DLP投影<font color='red'>STM32</font>单片机驱动电路研究设计
STM32与PID算法
一、总体原则 PID调试一般原则 a.在输出不振荡时,增大比例增益P。 b.在输出不振荡时,减小积分时间常数Ti。 c.在输出不振荡时,增大微分时间常数Td。 二、各环节作用 比例调节作用:是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例作用大,可以加快调节,减少误差,但是过大的比例,使系统的稳定性下降,甚至造成系统的不稳定。反之,过小,更不上系统需求。 积分调节作用:是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti,Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调
[单片机]
基于大功率LED灯的配光与散热技术研究
   1 背景   半导体器件的发光现象从原理上来说可以大致分为三种:光致发光,电致发光,阴极射线发光,其中第一种发光形式是当一定数量的光线照射到半导体上面的时候,半导体本身的电子和空穴吸收了光的能量而发光的现象。第二种发光形式是当在半导体器件上施加正向电压的时候,电子和空穴由于得到了能量而运动,进而激发了发光现象。   阴极射线发光是当某些射线照射到半导体上面的时候,半导体的载流子吸收了能量,进而产生复合发光的发光现象。    LED 本身也属于半导体器件,LED的自发性发光是由于电子和空穴之间的复合运动而产生的。它的发光原理是基于电致发光的发光原理,而没有采用与传统光源诸如白炽灯,节能灯等相似的发光原理。LED最重要的部分是
[电源管理]
基于大功率<font color='red'>LED灯</font>的配光与散热技术研究
STM32学前班教程之二:怎么开发-入门需知
该产品为简易STM32调试器和DEMO板一体化的调试学习设备,价格在一百多块。 2、硬件配置 仿真部分:USB口,reset,指示灯,JTAG DEMO部分:4按键(IO),4LED(IO),一个串口,启动方式跳线,所有引脚的焊盘(可自行焊接插针进行扩展) DEMO芯片:STM32F103C8T6(程序空间64K) 参数和扩展: 注:学习的目标芯片是STM32F103CBT6(7 7mm,128K flash,16K RAM)以及STM32F103RET6(10 10mm,512K flash,64K RAM)。 STM32-SK的硬件连接方法(用板载调试器调试板载DEMO): JP3、JP5 须全部短接 USB通
[单片机]
基于STM32四轴飞行器参考电路设计
四轴飞行器是一种利用四个旋翼作为飞行引擎来进行空中飞行的飞行器。进入20世纪以来,电子技术飞速发展四轴飞行器开始走向小型化,并融入了人工智能,使其发展趋于无人机,智能机器人。 四轴飞行器不但实现了直升机的垂直升降的飞行性能,同时也在一定程度上降低了飞行器机械结构的设计难度。四轴飞行器的平衡控制系统由各类惯性传感器组成。在制作过程中,对整体机身的中心、对称性以及电机性能要求较低,这也正是制作四轴飞行器的优势所在,而且相较于固定翼飞机,四轴也有着可垂直起降,机动性好,易维护等优点。 系统方案 本设计采用STM32F4作为核心处理器,该处理器内核架构 ARM Cortex-M4,具有高性能、低成本、低功耗等特点。 设计总
[单片机]
基于<font color='red'>STM32</font>四轴飞行器参考电路设计
STM32学习笔记 | SPI通信异常分析
SPI,全称为 Serial Peripheral Interface(串行外设接口) ,是一种用于短距离通信的同步串行通信接口,主要应用在嵌入式系统。 SPI的应用场合很广,显示模组、时钟芯片、存储芯片、温度传感器等众多器件都有使用SPI接口通信。这些器件通常作为从设备,STM32作为主设备来控制它们。 STM32 SPI基础内容 绝大部分STM32芯片都有多个SPI外设,它可与外部SPI器件进行半双工/全双工同步串行通信。 1. SPI特性 三条线全双工、双线单工同步传输 支持 8 位或 16 位传输帧格式选择 支持主模式或从模式操作 可编程的时钟极性和相位 支持 MSB 或 LSB 数据顺序 支持DMA收
[单片机]
<font color='red'>STM32</font>学习笔记 | SPI通信异常分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

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