本帖最后由 yuyy1989 于 2023-7-13 20:37 编辑
#申请原创# @21小跑堂
4.按键+定时器测试
先整理了一下开发板支持文件,因为工程只针对APM32F407IG Tiny Board,便将其它板子的文件都删掉了,目录结构变成了这样
把目录下的几个bsp文件也都加到了工程中
bsp的头文件有包含main.h,但是我自己创建的这个工程并没有这个文件,就都改成了Board_APM32F407_TINY.h,另外修改的时候发现Board_APM32F407_TINY中的bsp_usart.c中的串口初始化函数中写的还是APM_MINI_COMInit,应该是官方漏改了,不过也在这里给官方提个意见,这些开发板支持函数还是不要加什么MINI TINY的了,不然的话如果要把例程移植到其它板子上还要去替换这些函数名,一不小心就会有像前面提到的那样有漏掉的,如果能保持一致就省事多了
4.1 按键轮询
通过不断的查询按键电平状态来判断按键是否有按下,由于按下键时有可能会抖动所以延时一下再次判断电平,简单实现按键1 2控制LED2 3亮灭的代码
代码示例
#include "Board_APM32F407_TINY.h"
#include "bsp_delay.h"
int main(void)
{
APM_DelayInit();
APM_TINY_LEDInit(LED2);
APM_TINY_LEDInit(LED3);
APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
while (1)
{
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
{
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
{
while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
APM_TINY_LEDToggle(LED2);
}
}
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
{
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
{
while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
APM_TINY_LEDToggle(LED3);
}
}
}
}
void SysTick_Handler(void)
{
APM_DelayTickDec();
}
编译烧录查看效果
4.2 按键中断
配置按键IO在下降沿时产生中断,由于按下键时有可能会抖动导致多次中断,还是需要延时判断一下按键电平
代码示例
#include "Board_APM32F407_TINY.h"
#include "bsp_delay.h"
uint8_t key1down = 0;
uint8_t key2down = 0;
int main(void)
{
APM_DelayInit();
APM_TINY_LEDInit(LED2);
APM_TINY_LEDInit(LED3);
APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_EINT);
APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_EINT);
while (1)
{
if(key1down > 0)
{
key1down = 0;
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
APM_TINY_LEDToggle(LED2);
}
if(key2down > 0)
{
key2down = 0;
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
APM_TINY_LEDToggle(LED3);
}
}
}
void EINT15_10_IRQHandler(void)
{
if(EINT_ReadIntFlag(KEY1_BUTTON_EINT_LINE))
{
key1down = 1;
EINT_ClearIntFlag(KEY1_BUTTON_EINT_LINE);
}
if(EINT_ReadIntFlag(KEY2_BUTTON_EINT_LINE))
{
key2down = 1;
EINT_ClearIntFlag(KEY2_BUTTON_EINT_LINE);
}
}
void SysTick_Handler(void)
{
APM_DelayTickDec();
}
编译烧录查看效果
4.3 定时器
APM32F407有很多定时器定时器可用
用timer3做一个闪灯程序,按键切换闪烁速度
timer3是一个16位的定时器,从这张图中可以看到timer3的最大时钟是42M
之前对定时器时钟理解有误,对于定时器的频率还有额外描述
再来看看系统初始化时APB1和2的分频系数
所以timer3的时钟频率为84MHz,将timer3的时钟设置为1分频,预分频系数设置为42,计数周期设置为,1000就能得到一个每0.5ms触发一次的定时器
代码示例
#include "Board_APM32F407_TINY.h"
#include "bsp_delay.h"
#include "apm32f4xx_tmr.h"
volatile uint16_t tim3count = 0;
volatile uint16_t tim3countmax = 200;
void tim3_init()
{
TMR_BaseConfig_T TMR_TimeBaseStruct;
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
TMR_TimeBaseStruct.division = 41;
TMR_TimeBaseStruct.repetitionCounter = 0;
TMR_TimeBaseStruct.period = 999;
TMR_ConfigTimeBase(TMR3, &TMR_TimeBaseStruct);
TMR_EnableInterrupt(TMR3,TMR_INT_UPDATE);
NVIC_EnableIRQRequest(TMR3_IRQn, 0, 0);
TMR_Enable(TMR3);
}
int main(void)
{
APM_DelayInit();
APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
tim3_init();
while (1)
{
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
{
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
{
while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
tim3countmax = 500;
}
}
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
{
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
{
while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
tim3countmax = 200;
}
}
}
}
void SysTick_Handler(void)
{
APM_DelayTickDec();
}
void TMR3_IRQHandler(void)
{
if(TMR_ReadIntFlag(TMR3, TMR_INT_UPDATE) == SET)
{
if(tim3count < tim3countmax)
tim3count++;
else
{
tim3count = 0;
APM_TINY_LEDToggle(LED2);
APM_TINY_LEDToggle(LED3);
}
TMR_ClearIntFlag(TMR3, TMR_INT_UPDATE);
}
}
编译烧录查看效果
4.4 PWM输出
板子上的2个LED接的是PE5 PE6,可以使用timer9来实现pwm输出
写个程序两个按键分别控制LED的不同亮度,注意LED是低电平点亮,所以PWM要设置为低电平有效
代码示例
#include "Board_APM32F407_TINY.h"
#include "bsp_delay.h"
#include "apm32f4xx_tmr.h"
void pwm_init()
{
TMR_BaseConfig_T TMR_TimeBaseStruct;
TMR_OCConfig_T OCcongigStruct;
GPIO_Config_T GPIO_ConfigStruct;
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOE);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_5, GPIO_AF_TMR9);
GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_6, GPIO_AF_TMR9);
GPIO_ConfigStruct.pin = GPIO_PIN_5 | GPIO_PIN_6;
GPIO_ConfigStruct.mode = GPIO_MODE_AF;
GPIO_ConfigStruct.otype = GPIO_OTYPE_PP;
GPIO_ConfigStruct.speed = GPIO_SPEED_100MHz;
GPIO_Config(GPIOE, &GPIO_ConfigStruct);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR9);
TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
TMR_TimeBaseStruct.division = 83;
TMR_TimeBaseStruct.repetitionCounter = 0;
TMR_TimeBaseStruct.period = 999; //频率1k 占空比调节0-1000
TMR_ConfigTimeBase(TMR9, &TMR_TimeBaseStruct);
OCcongigStruct.mode = TMR_OC_MODE_PWM1; //PWM模式1,计数小于比较值时输出有效电平
OCcongigStruct.outputState = TMR_OC_STATE_ENABLE; //通道使能
OCcongigStruct.idleState = TMR_OC_IDLE_STATE_SET; //空闲高电平
OCcongigStruct.polarity = TMR_OC_POLARITY_LOW; //有效电平为低电平
OCcongigStruct.outputNState = TMR_OC_NSTATE_DISABLE; //互补通道失能
OCcongigStruct.nIdleState = TMR_OC_NIDLE_STATE_RESET;//互补通道空闲电平
OCcongigStruct.nPolarity = TMR_OC_NPOLARITY_HIGH; //互补通道有效电平
OCcongigStruct.pulse = 500; //初始50%
TMR_ConfigOC1(TMR9, &OCcongigStruct);
TMR_ConfigOC2(TMR9, &OCcongigStruct);
TMR_ConfigOC1Preload(TMR9, TMR_OC_PRELOAD_ENABLE);
TMR_EnableAutoReload(TMR9);
TMR_Enable(TMR9);
TMR_EnablePWMOutputs(TMR9);
}
int main(void)
{
APM_DelayInit();
APM_TINY_LEDInit(LED2);
APM_TINY_LEDInit(LED3);
APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
pwm_init();
while (1)
{
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
{
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
{
while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
TMR_ConfigCompare1(TMR9,900);
TMR_ConfigCompare2(TMR9,900);
}
}
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
{
APM_DelayMs(30);
if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
{
while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
TMR_ConfigCompare1(TMR9,100);
TMR_ConfigCompare2(TMR9,100);
}
}
}
}
void SysTick_Handler(void)
{
APM_DelayTickDec();
}
编译烧录,查看效果
|