前言
拿到板子有段时间了,但是一直没有上手实践,这次春节期间,正好抽出来一点时间上手试一试。本来以为和之前使用过的国产芯片,如GD32类似,但是在驱动LED和按键的时候就遇到了一些问题,所以本文重点是对这些问题做一些记录。
本文中的代码使用RT-Thread Studio开发,使用了RT-Thread OS。
新建工程
本来打算将RT-Thread OS集成到N32G457中的,但是我打开RT-Thread Studio新建工程的时候就发现官方已经集成好了,所以直接拿过来使用即可。
安装SDK
我的板子是N32G45XVL-STB,如下图安装SDK,其他型号的板子方法类似,选择自己手头板子的型号安装即可。
新建RT-Thread工程
选择“文件 -> 新建 -> RT-Thread项目”,然后进行如下配置。
到此工程就算新建完毕,可以直接编译下载了,下载之后的程序可以看到LED闪烁。
编写LED流水灯线程
按照RT-Thread一贯的操作流程:
新建线程,使能线程;
初始化三个LED的GPIO口为输出模式;
然后依次控制三个LED输出;
但是发现LED2(PB4)一直处于亮的状态,而且亮度也比较微弱,最开始还以为是LED坏掉了,但是查看了数据手册发现是PB4的默认工作方式是NJTRST模式,不是普通IO口。
所以通过重映射,将PB4设置为普通IO口就可以解决这个问题。
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST,ENABLE);
整个LED的控制代码如下,可以实现流水灯的逻辑。
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "app_led.h"
#define LED_TOTAL_NUM (3U)
#define LED3_PIN GET_PIN(B, 5)
#define LED2_PIN GET_PIN(B, 4)
#define LED1_PIN GET_PIN(A, 8)
typedef struct
{
rt_base_t led_pin;
rt_base_t led_val;
} s_LedCtrlType;
static rt_thread_t led_tid = RT_NULL;
static s_LedCtrlType led_ctrl[LED_TOTAL_NUM] =
{
{.led_pin = LED1_PIN, .led_val = PIN_HIGH},
{.led_pin = LED2_PIN, .led_val = PIN_LOW},
{.led_pin = LED3_PIN, .led_val = PIN_LOW}
};
static void Led_ThreadRunning(void *param);
static void Led_ThreadRunning(void *param)
{
uint8_t i;
rt_base_t temp_pin;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST,ENABLE);
rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
while(1)
{
temp_pin = led_ctrl[0].led_val;
for (i = 0; i < LED_TOTAL_NUM; i++)
{
rt_pin_write(led_ctrl[i].led_pin, led_ctrl[i].led_val);
if (i != (LED_TOTAL_NUM - 1))
{
led_ctrl[i].led_val = led_ctrl[i+1].led_val;
}
else
{
led_ctrl[i].led_val = temp_pin;
}
}
rt_thread_mdelay(500);
}
}
void Led_Init(void)
{
led_tid = rt_thread_create("led_thread",
Led_ThreadRunning,
RT_NULL,
2048,
20,
5);
if (led_tid != RT_NULL)
rt_thread_startup(led_tid);
}
编写按键线程
与上述控制LED同样的方式将KEY相关的三个引脚(PA4,PA5,PA6)设置为输入模式,但是发现按下按键之后根本就不工作,反馈的电平一直是0。
找了一段时间,发现是驱动模式设置的不对,驱动模式设置为上拉输入就可以了(PIN_MODE_INPUT_PULLUP)。
rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLUP);
完整代码如下,实现了40ms的按下/释放的软件滤波功能:
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "app_key.h"
#define KEY_TOTAL_NUM (3U)
#define KEY_PRESSED (1U)
#define KEY_RELEASED (0U)
#define KEY_FILTER_THD (4U)
#define KEY3_PIN GET_PIN(A, 6)
#define KEY2_PIN GET_PIN(A, 5)
#define KEY1_PIN GET_PIN(A, 4)
typedef struct
{
rt_base_t key_pin;
rt_base_t key_val;
uint8_t key_status;
uint8_t key_pre_status;
uint8_t key_pending_cnt;
} s_KeyCtrlType;
static rt_thread_t key_tid = RT_NULL;
static s_KeyCtrlType key_ctrl[KEY_TOTAL_NUM] =
{
{
.key_pin = KEY1_PIN,
.key_val = PIN_LOW,
.key_status = KEY_RELEASED,
.key_pre_status = KEY_RELEASED,
.key_pending_cnt = 0U
},
{
.key_pin = KEY2_PIN,
.key_val = PIN_LOW,
.key_status = KEY_RELEASED,
.key_pre_status = KEY_RELEASED,
.key_pending_cnt = 0U
},
{
.key_pin = KEY3_PIN,
.key_val = PIN_LOW,
.key_status = KEY_RELEASED,
.key_pre_status = KEY_RELEASED,
.key_pending_cnt = 0U
}
};
static void Key_ThreadRunning(void *param);
static void Key_ThreadRunning(void *param)
{
uint8_t i;
rt_base_t temp_pin;
rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLUP);
while(1)
{
for (i = 0; i < KEY_TOTAL_NUM; i++)
{
key_ctrl[i].key_val = rt_pin_read(key_ctrl[i].key_pin);
if (key_ctrl[i].key_val == PIN_LOW)
{
if (key_ctrl[i].key_pending_cnt < KEY_FILTER_THD)
key_ctrl[i].key_pending_cnt ++;
}
else
{
if (key_ctrl[i].key_pending_cnt > 0U)
key_ctrl[i].key_pending_cnt --;
}
if (key_ctrl[i].key_pending_cnt >= KEY_FILTER_THD)
{
key_ctrl[i].key_status = KEY_PRESSED;
}
else if (key_ctrl[i].key_pending_cnt == 0U)
{
key_ctrl[i].key_status = KEY_RELEASED;
}
key_ctrl[i].key_pre_status = key_ctrl[i].key_status;
rt_kprintf("Key%d: %d", i, key_ctrl[i].key_status);
}
rt_kprintf("\n");
rt_thread_mdelay(10);
}
}
void Key_Init(void)
{
key_tid = rt_thread_create("key_thread",
Key_ThreadRunning,
RT_NULL,
2048,
3,
5);
if (key_tid != RT_NULL)
rt_thread_startup(key_tid);
}