STM32F103 实验按键输入与串口实验

2019-08-19来源: eefocus关键字:STM32F103  按键输入  串口实验

正文

要进入按键输入,我们必须先明确,按键连在哪一个GPIO口,通过开发手册,如下

在这里插入图片描述

因此,我们可以在蜂鸣器和跑马灯的基础上,完成该实验。


按键输入

#include "led.h"

#include "delay.h"

#include "key.h"

#include "sys.h"

#include "beep.h"

#define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0

#define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1

#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) 


//#define KEY0 PEin(4)  PE4

//#define KEY1 PEin(3) PE3

//#define WK_UP PAin(0) PA0,作用跟上面一样,可替换


#define KEY0_PRES 1 //KEY0按下

#define KEY1_PRES 2 //KEY1按下

#define WKUP_PRES   3 //KEY_UP按下(即WK_UP/KEY_UP)


 int main(void)

 {

  vu8 key=0;

delay_init();     //延时函数初始化  

LED_Init();  

BEEP_Init();         

KEY_Init();          //初始化与按键连接的硬件接口

LED0=0; //先点亮红灯

while(1)

{

  key=KEY_Scan(0); //得到键值

  if(key)

{    

switch(key)

{  

case WKUP_PRES: //控制蜂鸣器

BEEP=!BEEP;

break; 

case KEY1_PRES: //控制LED1翻转

LED1=!LED1;

break;

case KEY0_PRES: //同时控制LED0,LED1翻转

LED0=!LED0;

LED1=!LED1;

break;

}

}else delay_ms(10); 

}  

}

void KEY_Init(void) //IO³õʼ»¯

  GPIO_InitTypeDef GPIO_InitStructure;

 

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//ʹÄÜPORTA,PORTEʱÖÓ


GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4|GPIO_Pin_3;//KEY0-KEY1

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入

  GPIO_Init(GPIOE, &GPIO_InitStructure);//


GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入 

GPIO_Init(GPIOA, &GPIO_InitStructure);

}


//0,没有按键按下

//1,KEY0按下

//2,KEY1按下

//3,KEY3按下 WK_UP

//响应优先级 KEY0>KEY1>KEY_UP!!

u8 KEY_Scan(u8 mode)

{  

static u8 key_up=1;//按键松开

if(mode)key_up=1;    

if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))

{

delay_ms(10);消抖

key_up=0;

if(KEY0==0)return KEY0_PRES; //1

else if(KEY1==0)return KEY1_PRES; //2

else if(WK_UP==1)return WKUP_PRES; //3

}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;     

  return 0;//无按键按下

}

void LED_Init(void)

{

GPIO_InitTypeDef  GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_SetBits(GPIOB,GPIO_Pin_5);  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;    

GPIO_Init(GPIOE, &GPIO_InitStructure);  

GPIO_SetBits(GPIOE,GPIO_Pin_5);  

}

void BEEP_Init(void)

{

 

GPIO_InitTypeDef  GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

GPIO_Init(GPIOB, &GPIO_InitStructure);  

 

GPIO_ResetBits(GPIOB,GPIO_Pin_8);


}


以上,我们设置一个按键是上拉输入,一个按键是下拉输入,那有什么区别呢?


1、上拉输入:上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻嵌位在高电平!电阻同时起限流作用!强弱只是上拉电阻的阻值不同,没有什么严格区分。

2、下拉输入:就是把电压拉低,拉到GND。与上拉原理相似。

对于KEY0和KEY1,通过上拉电阻,把引脚的电平嵌位在高电平,当按键按下时,按引脚电平转变成低电平。而对于WK_UP,因为是高电平触发,因此我们把它拉低。




串口实验

#include "led.h"

#include "delay.h"

#include "key.h"

#include "sys.h"

#include "usart.h"

 

 int main(void)

 {

  u16 t;  

u16 len;

u16 times=0;

delay_init();      

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 

//设置NVIC中断分组2:2位抢占优先级,2位响应优先级

uart_init(115200); //串口初始化为115200

  LED_Init(); //LED端口初始化

KEY_Init();          //初始化与按键连接的硬件接口

  while(1)

{

//接收状态

//bit15 接收完成标记

//bit14£¬ 接收到oxod

//bit13~0   接收到的有效字节数目

//u16 USART_RX_STA=0;       //接收状态标记

if(USART_RX_STA&0x8000) //如果接受到数据...

{    

len=USART_RX_STA&0x3fff;//得到数据长度

printf("rn你发送的消息为:rnrn");

for(t=0;t

{

USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据

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

}

printf("rnrn");//插入换行

USART_RX_STA=0;

}else

{

times++;

if(times%200==0)printf("请输入数据n");  

if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行

delay_ms(10);   

}

}  

 }

 void uart_init(u32 bound){

//GPIO端口设置

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟


//USART1_TX   GPIOA.9

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

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

GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9


//USART1_RX   GPIOA.10初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10

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

GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  


//Usart1 NVIC 配置

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); //根据指定的参数初始化VIC寄存器


//USART 初始化设置


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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断

USART_Cmd(USART1, ENABLE);                    //使能串口1 


}

void USART1_IRQHandler(void)                //串口1中断服务程序

{

u8 Res;

#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.

OSIntEnter();    

#endif

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)

{

Res =USART_ReceiveData(USART1); //读取接收到的数据


if((USART_RX_STA&0x8000)==0)//接收未完成

{

if(USART_RX_STA&0x4000)//接收到了0x0d

{

if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始

else USART_RX_STA|=0x8000; //接收完成了 

}

else //还没收到0X0D

{

if(Res==0x0d)USART_RX_STA|=0x4000;

else

{

USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;

USART_RX_STA++;

if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收   

}  

}

}     

#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.

OSIntExit();   

#endif


运行结果如下:


在这里插入图片描述

关于串口

ALIENTEK精英STM32开发板所使用的STM32F103ZET6最多可提供5路串口,有分数波特率发生器,支持同步单线通信和半双工单线通讯,支持LIN,支持调制解调器操作,智能卡协议和IrDA SIR ENDEC规范,具有DMA等。


void uart_init(u32 bound)函数是串口1初始化函数

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA,ENABLE);

//使用USART1,GPIOA,该口具有复用功能


接下来,我们要初始化相应的GPIO端口为特定的状态,如下:

在这里插入图片描述

所以需要配置TX(PA9)设置为推挽复用输出模式,将RX(PA10)设置为浮空输入模式


 //USART1_TX   PA.9     

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.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_Mode = GPIO_Mode_IN_FLOATING;//浮空输入     

 GPIO_Init(GPIOA, &GPIO_InitStructure);   


紧接着,我们要进行usart1的中断初始化,设置抢占优先级值和子优先级的值:


//Usart1 NVIC 中断配置

[1] [2]

关键字:STM32F103  按键输入  串口实验

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic471634.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32学习第一周之 循环显示RGBLED的七种颜色
下一篇:STM32F103 时钟系统明晰

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

关于STM32f103 SPI时钟速度的问题

STM32f103 中APB1的最高频率是36MHz,APB2的最高频率是72MHz,而PCLK1和PCLK2一般也默认配置为其最高工作频率36M和72M。如下图(STM32F10xx_参考手册(第7版) 第46页)时钟树所示:SPI1时钟由APB2时钟分频而来,可以选择2、4、8、16、32、64、128、256这几个分频系数。而手册规定STM32的SPI时钟最快是18MHz。对于STM32F103的SPI1接口时钟,由72M的PCLK2分频得到,所以分配系数大于等于4(72M/4 = 18M)。对于STM32F103的SPI2/SPI3接口时钟,由36M的PCLK1分频得到,所以分配系数大于等于2(36M/2 = 18M
发表于 2019-09-12
关于STM32f103 SPI时钟速度的问题

STM32F4 HAL库DMA学习

;            对DMA的个别寄存器的参数进行填充,比如调用 HAL_DMA_Start()函数就会调用DMA_SetConfig()函数配置数据个数、源地址、目的地址等。而hdmatx 和第二步的DMA句柄是一模一样的,感觉最后转了一圈又转回会来了。。。  (4)  外设初始化、DMA初始化、外设和DMA进行关联、外设使能DMA发送或者接收、DMA调用函数开始发送或者接收。 个人感觉有时候HAL库的确有些冗余了,这时候可能就需要部分进行寄存器操作了。二、使用过程总结1、传输数据数目设置 注意传输数据的个数的设置:如果源
发表于 2019-09-11

STM32F103C8T6使用普通IO口模拟串口收发

在单片机用基本定时器来完成这样的事情。。。。即完成非阻塞式通讯!(1)定时器开启如下:(2)调用发送函数:UART4_Send_Buf(...);//注意STM32F103C8t6是没有串口4的!!!这是虚拟串口!!(3)调用的发送函数里面开启了定时器,所以接下来将在定时期中断中进行发送操作发送函数模拟了串口的时序:开始-发送-结束发送完一个字节,然后从缓冲区callback(),调用下一个字节进行传输!代码段如下:static void send_remain_byte(void){ if(VirtualUart.send_cnt>=VirtualUart.send_max) { VirtualUart.send_flag
发表于 2019-09-11
STM32F103C8T6使用普通IO口模拟串口收发

STM32F103的W25Q64的DMA高效数据访问实现

** Descriptions:            none**------------------------------------------------------------------------------** HW_CMU:                  STM32F103ZET6** Libraries:               STM32F10x_St
发表于 2019-09-11

STM32F103C8T6 Standby低功耗模式

1. 开发环境:winXPMDK4.45STM32 3.5固件库2. 低功耗模式简介刚接触PWR的内容,使用手册说的不太能让我好理解。其实当你弄懂了以后再回去看使用手册还是能找到的,只是写的过于简略,对于初学者很多地方理解不到位。 这个小总结完全从初学者角度,目的只有一个:进入/唤醒 PWR的standby模式。其实更多的是如何配置进入,唤醒基本上是配置好了后自动完成或硬件出发的,我们需要做的退出后的设计。这块内容暂不作为本次讨论内容。NVIC  和 PWR 各寄存器状态决定三种低功耗模式:低功耗模式一览表 PS: STM32F的NRST是异步复位脚。当NRST输入低电平的时候,MCU处于
发表于 2019-09-11
STM32F103C8T6 Standby低功耗模式

关于STM32F107VCT6串口DMA接收数字控制LED亮灭的功能实现

主函数中代码如下:#include "stm32f10x.h"void GPIO_Config(void);void USART_Config(void);void DMA_Config(void);void NVIC_Config(void);void LED1_ON(void);void LED2_ON(void);void LED3_ON(void);void LED4_ON(void);void LED_ALL_OFF(void);void delay(void);uint8_t DMA_BUFFER[1]; int main(){       
发表于 2019-09-10
关于STM32F107VCT6串口DMA接收数字控制LED亮灭的功能实现

小广播

何立民专栏

单片机及嵌入式宝典

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

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