之前的帖子使用例程完成了简单的点灯测试,这次自己新建个工程来进行测试,完成基础题目中的这两个
先新建个文件夹,把固件包里的Device文件夹复制过去,另外再新建2个文件夹用来存放keil工程文件和代码文件
打开keil,选择新建工程,保存目录选择刚才新建的文件夹(MDK),芯片选择MM32F5333D7PV
接下来的页面直接点OK就行,按照自己的习惯添加好分组
将Device中的库文件添加进来
添加头文件路径
参考例程添加宏定义
修改linker
添加main.c
先简单写个流水灯测试一下,查看原理图确定LED使用的引脚
编写代码,LED是低电平点亮,初始化后输出高电平使LED初始状态为熄灭
#include "hal_conf.h"
enum
{
LED_NO_1 = 0,
LED_NO_2,
LED_NO_3,
LED_NO_4,
LED_NUM,
};
GPIO_TypeDef *led_ports[] = {GPIOB,GPIOB,GPIOC,GPIOC};
uint16_t led_pins[] = {GPIO_Pin_11,GPIO_Pin_10,GPIO_Pin_7,GPIO_Pin_6};
void led_init(void)
{
uint8_t i = 0;
GPIO_InitTypeDef cfg;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_StructInit(&cfg);
cfg.GPIO_Mode = GPIO_Mode_Out_PP;
cfg.GPIO_Speed = GPIO_Speed_High;
while(i < LED_NUM)
{
cfg.GPIO_Pin = led_pins[i];
GPIO_Init(led_ports[i],&cfg);
GPIO_SetBits(led_ports[i],led_pins[i]);
i += 1;
}
}
void led_toggle(uint8_t led)
{
if(led < LED_NUM)
GPIO_WriteBit(led_ports[led], led_pins[led], !GPIO_ReadOutputDataBit(led_ports[led], led_pins[led]));
}
void test_delay(void)
{
uint32_t delay = 0x100000;
while(delay--);
}
int main(void)
{
led_init();
while (1)
{
test_delay();
led_toggle(LED_NO_1);
test_delay();
led_toggle(LED_NO_2);
test_delay();
led_toggle(LED_NO_3);
test_delay();
led_toggle(LED_NO_4);
}
}
编译并烧录,运行效果
接下来实现按键检测,通过点击按键切换LED状态,先来看原理图
按键1是高电平触发,剩下三个都是低电平触发,并且按键2、3、4没有上拉电阻,在配置时需要开启内部上拉,机械按键按下时会产生抖动,这里对按下状态进行计时,按下状态持续20ms视为触发点击操作,然后切换对应LED的状态,代码如下
GPIO_TypeDef *key_ports[] = {GPIOC,GPIOC,GPIOB,GPIOB};
uint16_t key_pins[] = {GPIO_Pin_4,GPIO_Pin_5,GPIO_Pin_1,GPIO_Pin_2};
const uint8_t key_press_states[] = {Bit_SET,Bit_RESET,Bit_RESET,Bit_RESET};
uint8_t key_press_counts[KEY_NUM];
void keys_init(void)
{
GPIO_InitTypeDef cfg;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_StructInit(&cfg);
cfg.GPIO_Mode = GPIO_Mode_IPU;
cfg.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOC,&cfg);
cfg.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_Init(GPIOB,&cfg);
cfg.GPIO_Mode = GPIO_Mode_FLOATING;
cfg.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOC,&cfg);
memset(key_press_counts,0,KEY_NUM);
}
void key_state_check(void)
{
uint8_t i = 0;
while(i < KEY_NUM)
{
if(GPIO_ReadInputDataBit(key_ports[i], key_pins[i]) == key_press_states[i])
{
if(key_press_counts[i] < 0xFF)
key_press_counts[i] += 1;
}
else
key_press_counts[i] = 0;
if(key_press_counts[i] == 20)
led_toggle(i);
i += 1;
}
}
int main(void)
{
led_init();
keys_init();
while (1)
{
YUYY_DelayMs(1);
key_state_check();
}
}
运行效果
上面是通过不断查询io电平来实现的按键检测,接下来通过中断来进行按键检测,所有 IO 引脚可以连接到 16 个外部中断线,对应关系如下图
配置按键1为上升沿触发,其他3个为下降沿触发,代码如下
void exit_init(void)
{
EXTI_InitTypeDef exit_cfg;
NVIC_InitTypeDef nvic_cfg;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource4);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource5);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource1);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource2);
EXTI_StructInit(&exit_cfg);
exit_cfg.EXTI_Line = EXTI_Line4;
exit_cfg.EXTI_Mode = EXTI_Mode_Interrupt;
exit_cfg.EXTI_Trigger = EXTI_Trigger_Rising;
exit_cfg.EXTI_LineCmd = ENABLE;
EXTI_Init(&exit_cfg);
nvic_cfg.NVIC_IRQChannel = EXTI4_IRQn;
nvic_cfg.NVIC_IRQChannelPreemptionPriority = 0;
nvic_cfg.NVIC_IRQChannelSubPriority = 1;
nvic_cfg.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_cfg);
exit_cfg.EXTI_Line = EXTI_Line5;
exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&exit_cfg);
nvic_cfg.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_Init(&nvic_cfg);
exit_cfg.EXTI_Line = EXTI_Line1;
exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&exit_cfg);
nvic_cfg.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_Init(&nvic_cfg);
exit_cfg.EXTI_Line = EXTI_Line2;
exit_cfg.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&exit_cfg);
nvic_cfg.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_Init(&nvic_cfg);
}
void EXTI4_IRQHandler(void)
{
if (SET == EXTI_GetITStatus(EXTI_Line4) && GPIO_ReadInputDataBit(key_ports[KEY_NO_1], key_pins[KEY_NO_1]) == key_press_states[KEY_NO_1])
{
led_toggle(LED_NO_1);
EXTI_ClearITPendingBit(EXTI_Line4);
}
}
void EXTI9_5_IRQHandler(void)
{
if (SET == EXTI_GetITStatus(EXTI_Line5) && GPIO_ReadInputDataBit(key_ports[KEY_NO_2], key_pins[KEY_NO_2]) == key_press_states[KEY_NO_2])
{
led_toggle(LED_NO_2);
EXTI_ClearITPendingBit(EXTI_Line5);
}
}
void EXTI1_IRQHandler(void)
{
if (SET == EXTI_GetITStatus(EXTI_Line1) && GPIO_ReadInputDataBit(key_ports[KEY_NO_3], key_pins[KEY_NO_3]) == key_press_states[KEY_NO_3])
{
led_toggle(LED_NO_3);
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI2_IRQHandler(void)
{
if (SET == EXTI_GetITStatus(EXTI_Line2) && GPIO_ReadInputDataBit(key_ports[KEY_NO_4], key_pins[KEY_NO_4]) == key_press_states[KEY_NO_4])
{
led_toggle(LED_NO_4);
EXTI_ClearITPendingBit(EXTI_Line2);
}
}
int main(void)
{
led_init();
keys_init();
exit_init();
while (1)
{
}
}
运行效果和轮询的类似,这里就不再重复上图了
|