emmnn 发表于 2022-7-11 16:35

【国民技术低功耗系列N32L43x测评】3、按键驱动+SPI_LCD屏驱

本帖最后由 emmnn 于 2022-7-11 16:36 编辑

**目录 (Table of Contents)**



# 前言
在介绍完RTOS的移植后,今天介绍的是按键驱动和SPI-LCD屏驱的开发及功能演示。
#按键驱动
在官方提供的开发板上,除了reset和wakeup按键外,还提供了三个按键供我们使用。为了方便后续的应用开发,我找了一颗五向开关,另外接了其他IO做演示。

这种按键共有6个引脚,其中一个引脚接地,剩余5个引脚代表5个方向(上下左右以及按下)

将该开关引脚引出来,接到开发板空闲的IO上,并定好宏定义
```c
#define KEY_PORT_GROUP      GPIOB
#define KEY_RCC_PERIPH      RCC_APB2_PERIPH_GPIOB

#define KEY_UP_PIN          GPIO_PIN_2
#define KEY_DOWN_PIN      GPIO_PIN_11
#define KEY_LEFT_PIN      GPIO_PIN_10
#define KEY_RIGHT_PIN       GPIO_PIN_1
#define KEY_PRESSED_PIN   GPIO_PIN_0
```
剩下的就是很简单的IO初始化及读IO获取按键状态的操作,具体代码可以查看附件工程。
在使用单片机做嵌入式开发中,按键可以说是最常见的一个模块。虽说对于MCU端来说,它要做的就是很简单的读IO操作,但是实际开发中,要考虑的问题点还是挺多的。比如如何做按键消抖处理,以及在实际应用中,对于各类按键事件(如短按,长按,单击,双击)如何做判断及处理。同时如何保证整个按键应用处理的业务逻辑能保持清晰不乱,完成功能的同时要把这些都做好,这还是挺难的。这里之所以把按键这部分单独拿出来讲,主要是想安利下最近在刷到的在Github上开源的一个简单易用的事件驱动型按键驱动模块。
GitHub地址如下:(https://github.com/0x1abin/MultiButton)
代码由纯C编写,代码简洁,可读性也特别好,200行左右的代码,就实现了按键的各类触发事件,可扩展性也很好,业务逻辑也很清晰(在这里默默地膜拜大佬)。
```c
/**
* @brief 按键事件及回调注册
*
* @return uint8_t
*/
uint8_t KeyRegister(void)
{
    button_init(&dev_handler_s.dev_btn_s.btn_up, KeyScan, 0, KEY_UP_ID);
        button_init(&dev_handler_s.dev_btn_s.btn_down, KeyScan, 0, KEY_DOWN_ID);
    button_init(&dev_handler_s.dev_btn_s.btn_left, KeyScan, 0, KEY_LEFT_ID);
        button_init(&dev_handler_s.dev_btn_s.btn_right, KeyScan, 0, KEY_RIGHT_ID);
    button_init(&dev_handler_s.dev_btn_s.btn_ok, KeyScan, 0, KEY_PRESSED_ID);

    button_attach(&dev_handler_s.dev_btn_s.btn_up, SINGLE_CLICK,BtnUp_Single_Clicked_Handler);
        button_attach(&dev_handler_s.dev_btn_s.btn_down, SINGLE_CLICK, BtnDown_Single_Clicked_Handler);
    button_attach(&dev_handler_s.dev_btn_s.btn_left, SINGLE_CLICK,BtnLeft_Single_Clicked_Handler);
        button_attach(&dev_handler_s.dev_btn_s.btn_right, SINGLE_CLICK, BtnRight_Single_Clicked_Handler);
    button_attach(&dev_handler_s.dev_btn_s.btn_ok, SINGLE_CLICK,BtnOk_Single_Clicked_Handler);
    button_attach(&dev_handler_s.dev_btn_s.btn_ok, DOUBLE_CLICK,BtnOk_Single_Clicked_Handler);

    button_start(&dev_handler_s.dev_btn_s.btn_up);
        button_start(&dev_handler_s.dev_btn_s.btn_down);
    button_start(&dev_handler_s.dev_btn_s.btn_left);
        button_start(&dev_handler_s.dev_btn_s.btn_right);
    button_start(&dev_handler_s.dev_btn_s.btn_ok);

    dev_handler_s.dev_btn_s.btn_Timer = rt_timer_create("BTN Timer",
                                                                                                BtnTimerCb,
                                                                                                RT_NULL,
                                                                                                5,
                                                                                                RT_TIMER_FLAG_PERIODIC);
    if (dev_handler_s.dev_btn_s.btn_Timer != RT_NULL)
      rt_timer_start(dev_handler_s.dev_btn_s.btn_Timer);
}
```
根据例程演示,移植到我的工程上后,按键部分实现了我想要的效果。(源码部分只有200行左右,有时间的可以仔细研读下大佬的代码,学习下他的编程思想,可以学习到很多东西的)。

#SPI-LCD屏驱动
讲完了按键驱动模块,接下来讲解下使用MCU的SPI接口来驱动LCD屏。关于屏的话是某宝上很常见的SPI接口的屏,卖家也会提供一些示例驱动代码。

翻看芯片的数据手册及用户手册,得知该MCU有两路SPI外设接口可供我们使用。这里我们使用SPI2,查看数据手册关于引脚复用定义说明,我们使用PB13和PB15分别复用为SPI2的CLK和MOSI脚。

其他引脚定义如下
```c
#define SPI_SCK_RCC_PERIPH      (RCC_APB2_PERIPH_GPIOC)
#define SPI_RCC_PERIPH          (RCC_APB2_PERIPH_GPIOB)//RCC_APB2_PERIPH_GPIOA

/* RES Port/Pin definition */
#define RES_PORT                (GPIOB)
#define RES_PIN               (GPIO_PIN_14)
/* DC Port/Pin definition */
#define DC_PORT               (GPIOC)
#define DC_PIN                  (GPIO_PIN_7)
/* BLK Port/Pin definition */
#define BLK_PORT                (GPIOB)
#define BLK_PIN               (GPIO_PIN_12)

#define SPI_PERIPH            (SPI2)
#define SPI_LCD_CLK             (RCC_APB2_PERIPH_SPI2)

/* Define port and pin for SDA and SCL */
#define SPI_SCK_PORT            (GPIOB)
#define SPI_SCK_PIN             (GPIO_PIN_13)

#define SPI_MOSI_PORT         (GPIOB)
#define SPI_MOSI_PIN            (GPIO_PIN_15)
```
其他部分参考官方例程和屏驱动例程,修改下,屏也能正常点亮。
#效果演示图

#问题点记录
在使用SPI接口驱动LCD屏的过程中,发现了一个问题。一开始,我使用的是PC7和PB15复用为SPI2的SCK和MOSI来驱动LCD,但是实际在使用过程中,用逻辑分析仪抓信号发现时钟引脚SCK始终没有信号输出,后将SCK引脚改为PA10亦是如此。将SCK改到PB13,也就是跟MOSI同属一个GPIO组后,SPI就能正常使用输出信号。不清楚是不是该单片机对于SPI的使用,IO口必须强制要求同属一个GPIO组,本人没有花时间去做更多的验证,之前在其他产家的MCU没遇到过这种问题,在官方提供的文档中也暂时没看到相关的说明。若是有大佬知道问题所在,还希望能帮忙解惑下。:Onion-39:最后工程的附件如下:
#附件

lugl4313820 发表于 2022-7-11 17:41

楼主是用的硬件SPI来驱动的吗?如果是软件SPI可以使用不同的端口,如果是硬件SPI,常规来讲应该是一个端口的吧,详细要看一下数据手册吧。

luojiazidi_87 发表于 2022-7-11 18:08

<p>,但是实际开发中,要考虑的问题点还是挺多的。比如如何做按键消抖处理,以及在实际应用中,对于各类按键事件(如短按,长按,单击,双击)如何做判断及处理。同时如何保证整个按键应用处理的业务逻辑能保持清晰不乱,完成功能的同时要把这些都做好,这还是挺难的。这里之所以把</p>

<p>&nbsp;</p>

freebsder 发表于 2022-7-11 19:33

<p>图文并茂,还做了目录,楼主用心了。</p>

emmnn 发表于 2022-7-11 22:04

lugl4313820 发表于 2022-7-11 17:41
楼主是用的硬件SPI来驱动的吗?如果是软件SPI可以使用不同的端口,如果是硬件SPI,常规来讲应该是一个端口的 ...

<p>使用的是硬件SPI来驱动的,前阵子公司产品使用过华大的芯片就没这个问题</p>

lugl4313820 发表于 2022-7-11 22:12

luojiazidi_87 发表于 2022-7-11 18:00
,但是实际开发中,要考虑的问题点还是挺多的。比如如何做按键消抖处理,以及在实际应用中,对于各类按键事 ...

<p>看样子您是新人,可能是需要赚取一些积分,希望您用心阅读作者的帖子后,再回复有意义的帖子,也是对楼辛苦发帖的尊重。加油!</p>

eew_DPB3w3 发表于 2022-8-16 19:46

我看你的代码重映射是AF0, PB13对应是AF0。是不是配置PA10、PC7作为SCK时,没有配置重映射为AF5,GPIO_InitStructure.GPIO_Alternate = GPIO_AF5_SPI2;
页: [1]
查看完整版本: 【国民技术低功耗系列N32L43x测评】3、按键驱动+SPI_LCD屏驱