首页 > 其他分享 >STM32掌机教程3,工程模板与带灯按键测试

STM32掌机教程3,工程模板与带灯按键测试

时间:2023-01-11 12:35:41浏览次数:38  
标签:DOWN LED Pin STM32 GPIO 带灯 掌机 PRES define


我们需要“脚手架”

  关于代码,我想体现出这么一个过程:我是如何一步一步修改代码的。我认为,从学习的角度来考虑,直接看最终的代码没有什么意义。 写代码就像工人盖房子,盖房子过程中,工人要搭建脚手架;房子盖好以后,脚手架要拆除。直接领着学生看盖好的房子,说,你就照着这个样子来盖房子,学生是做不出来。他不知道怎么搭建脚手架,甚至都不知道什么是脚手架。 所以我打算这个系列的讲义,每一篇代码都在上一篇的基础上做一些改进,保留代码“进化”的过程。有些过程代码在最终的代码中不会体现,但是也很重要,就像房子盖好以后,你看不到脚手架一样。我们需要脚手架。

STM32掌机教程3,工程模板与带灯按键测试_掌机


  目前用到的代码先用压缩包的形式上传,等教程写完以后,后续代码的维护使用Git。

各种初始化

  下载压缩包并打开工程以后,可以在main.c里找到主函数。目前为止,主函数进行了一些初始化,死循环内什么都没写,后续可以根据我们的需要写业务逻辑代码。

//main.c
int main(void)
{
LED_Init();
KEY_Init();
delay_init();
initIIC();
initOLED();

while(1)
{


}
}

LED与SLED的初始化

  函数的作用从名字就可以看出来,比较简单。例如LED的初始化。需要初始化哪个引脚,可以从电路图中看出。

STM32掌机教程3,工程模板与带灯按键测试_初始化_02

//IO.c
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
GPIO_Init(GPIOC, &GPIO_InitStructure);

AllLED_ON();
LED1 = LED_ON;
LED2 = LED_OFF;
}

  具体LED或者SLED对应的引脚可以在原理图中看出来。为了方便使用,我根据外设与引脚关系做了宏定义。

//IO.h
#define SLED1 PCout(0)
#define SLED2 PCout(1)
#define SLED3 PCout(2)
#define SLED4 PCout(3)
#define LED1 PCout(4)
#define LED2 PCout(5)
#define SLED5 PBout(12)
#define SLED6 PBout(13)
#define SLED7 PBout(14)
#define SLED8 PBout(15)
#define SKEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define SKEY2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)
#define SKEY3 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)
#define SKEY4 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)
#define SKEY5 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)
#define SKEY6 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_7)
#define SKEY7 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_8)
#define SKEY8 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9)

#define PAUSE GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)
#define BEEP PBout(1)

#define KEY1_PRES 1 //KEY1按下
#define KEY2_PRES 2 //KEY2按下
#define KEY3_PRES 3 //KEY3按下
#define KEY4_PRES 4 //KEY4按下
#define KEY5_PRES 5 //KEY5按下
#define KEY6_PRES 6 //KEY6按下
#define KEY7_PRES 7 //KEY7按下
#define KEY8_PRES 8 //KEY8按下
#define PAUSE_PRES 9

#define LED_ON 0
#define LED_OFF 1
#define DOWN 0 //按键按下
#define FREE 1

  然后编写了两个函数,用于点亮所有LED或者关闭所有LED

//IO.c
void AllLED_ON(void)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
GPIO_ResetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
}
void AllLED_OFF(void)
{
GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
}

  这些代码。可能对于某些没有使用过STM32的同学来说不太好看懂,不过没有关系,可以仅仅应用的话,这是很简单的。在我之前的博客里也提过一些库函数的基础。例如设置某引脚为推挽输出​​GPIO_Mode_Out_PP​​​ ,不知道什么事推挽输出可以自己查一下。设置哪个引脚为推挽输出?PB12到PB15,PC0到PC5。
  再比如,让某个LED亮起来​​​GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);​​很容易看出来,这个操作是把PB12到PB15置为低电平,结合原理图可知,引脚低电平可以点亮LED。

按键初始化与扫描函数

  按键设置为上拉输入,检测到低电平,说明按键被按下。按键扫描函数课可以返回被按下的按键值。

void KEY_Init(void)  //PB0-PB3
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/*
//PB3与PB4默认用作调试口,如果用作普通的IO,需要加上以下两句
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
GPIO_Init(GPIOC, &GPIO_InitStructure);

}
unsigned char KEY_Scan(unsigned char mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(SKEY1==DOWN||SKEY2==DOWN||SKEY3==DOWN||SKEY4==DOWN||SKEY5==DOWN||SKEY6==DOWN||SKEY7==DOWN||SKEY8==DOWN||PAUSE==DOWN))
{
delay_ms(10);//去抖动
key_up=0;
if(PAUSE==DOWN)return PAUSE_PRES;
else if(SKEY1==DOWN)return KEY1_PRES;
else if(SKEY2==DOWN)return KEY2_PRES;
else if(SKEY3==DOWN)return KEY3_PRES;
else if(SKEY4==DOWN)return KEY4_PRES;
else if(SKEY5==DOWN)return KEY5_PRES;
else if(SKEY6==DOWN)return KEY6_PRES;
else if(SKEY7==DOWN)return KEY7_PRES;
else if(SKEY8==DOWN)return KEY8_PRES;
}else if(SKEY1==FREE && SKEY2==FREE && SKEY3==FREE && SKEY4==FREE && SKEY5==FREE && SKEY6==FREE && SKEY7==FREE && SKEY8==FREE && PAUSE==FREE)key_up=1;
return 0;// 无按键按下
}

其它初始化

  延时函数的初始化借用了别人的代码,就不贴了。

  0.96OLED屏幕用到了IIC总线,所以既需要初始化IIC总线,也需要初始化OLED屏幕。其实初始化的代码也不是我写的,借用的。有的读者可能会说,屏幕的初始化好像挺难的,我不知道这些初始化函数怎么写出来。这个问题很好解决——如果厂家不提供初始化的代码,我们不买它的屏幕就行了。谁提供代码,提供技术支持,我们选谁的屏幕。毕竟

STM32掌机教程3,工程模板与带灯按键测试_初始化_03


  另外,对于定时器和蜂鸣器,我也写好了初始化代码。用到再说吧。

带灯按键检测

  在LED的初始化函数中,已经点亮了所有的带灯按键。如果按键上的灯不亮,就只能找硬件问题了。接下来写一小段测试代码,判断按键按下能否检测到。
  我的思路是,如果按下了某个按键,那么按键对应的LED灯状态翻转。STM32中,让引脚状态翻转其实是比较高阶的操作,原理比较复杂,感兴趣的可以搜下STM32的位带操作。但是用起来很简单,把寄存器当数据操作,假装寄存器可以取反。例如,LED1的状态取反​​​LED1 = !LED1​​​,如此操作,可以不用关心LED之前是亮是灭,看到的现象就是状态变了。
  我们可以写一个switch case语句,根据按键值来操作对应的LED。

while(1)
{
switch(KEY_Scan(0))
{
case PAUSE_PRES:
LED1 = !LED1;
LED2 = !LED2;
break;
case KEY1_PRES:
SLED1 = !SLED1;
break;
case KEY2_PRES:
SLED2 = !SLED2;
break;
case KEY3_PRES:
SLED3 = !SLED3;
break;
case KEY4_PRES:
SLED4 = !SLED4;
break;
case KEY5_PRES:
SLED5 = !SLED5;
break;
case KEY6_PRES:
SLED6 = !SLED6;
break;
case KEY7_PRES:
SLED7 = !SLED7;
break;
case KEY8_PRES:
SLED8 = !SLED8;
break;
default:
break;
}
}

  现象就是,上电以后,所有的按键灯都亮,如果按下某个按键,那么按键对应的灯状态翻转。


标签:DOWN,LED,Pin,STM32,GPIO,带灯,掌机,PRES,define
From: https://blog.51cto.com/u_12001544/6002121

相关文章

  • STM32自带GB2312字库显示汉字
      本文介绍如何把字库文件写入单片机的flash中,然后无需再提取字模,即可实现单片机显示中文字符的功能。下载字库到单片机flash中的指定位置  在​​上一篇博客​​中,最后......
  • STM32HAL库定时器中断关闭的方法
    本文可以用于解决这个问题:定时器中断上电后莫名其妙开启,或者首先触发一次。STM32HAL库在定时器初始化并开启以后,也是会默认开启中断。如不需要默认就开启中断可以用一下代......
  • HAL库教程2:使用STM32CubeMX新建一个工程
    安装STM32CubeMX  安装STM32CubeMX之前,电脑中要有java运行时环境(JRE),否则会报错:  双击JavaSetup8u201.exe即可安装JRE。在安装过程中,需要在线下载一些资源,所以应当保持......
  • HAL库教程1:STM32Cube的介绍
      使用STM32HAL库已经有了一段时间,觉得相比于标准库,好用了不少。加上STM32CubeMX图形化配置工具的加持,个人认为可以极大提升开发效率。其实关于HAL库的教程已经很多了,关于......
  • HAL库教程7:STM32的时钟系统
      STM32的时钟系统比较复杂,不像51单片机,可能只有一个时钟。原因:1、外设多,不同的外设有不同的时钟要求;2、功耗原因,速度越快,功耗越大,抗电磁干扰能力越弱。此处以STM32F405......
  • 进阶阶段——STM32学习笔记(一)
    进阶阶段——STM32学习笔记(1)前言由于套件放在学校,待等假期结束后才能做实验0STM32简介注意:STM32的标准工作电压为3.3V,若用5V供电,需要用(电平转换电路)稳压芯片降压至3.3......
  • STM32 - 中断
    1.中断定义(Event)中断(Interrupt):指当出现需要时,CPU暂时暂停当前程序的执行,转而执行处理新情况的程序的处理过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理......
  • Basic Concepts of STM32 (1)
           ......
  • STM32 - USART串口通信
    本文以正点原子-探索者开发板-STM32F407ZGT6为硬件平台进行代码讲解1.简介通用同步异步收发器(USART)能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标......
  • rt-thread 中pwm组件不起作用的问题 stm32L431
    board.h中打开如下定义,并新增要使用的通道#defineBSP_USING_PWM1/*#defineBSP_USING_PWM2*//*#defineBSP_USING_PWM3*/#defineBSP_USING_PWM1_CH1drv_pwm.c中......