SysTick讲解
SysTick是滴答定时器,在相应的时间间隔内对变量进行操作(通过执行SysTick中断函数实现)。所以在比赛和学习中被组合成准确延时函数。
SysTick模块的时钟电路可以参考芯片的手册,在这里不做过多的解释。
SysTick的初始化为
SysTick_Config(SystemCoreClock/100); //1ms中断一次
函数SysTick_Config定义在core_cm3.h中的第1543行。参数SystemCoreClock定义在system_stm32f10x.c中的第162行。因为比赛的时候会给LCD的参考例程,例程中有延时函数,所以SysTick的初始化无需可以记忆。以下有关SysTick的内容也是一样,都会提供代码,无需记忆,知道会运用就行。需要注意的是函数SysTick_Config的参数中的除数越小中断间隔越长,及延时越长。
运用SysTick组合成准确延时函数的代码为
/**
* @说明 延时函数
* @参数 nTime: 延时时间
* @返回值 None
*/
void Delay_Ms(uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
其中变量TimingDelay 需要在main.c文件的开头部分需要进行定义,定义的代码为
uint32_t TimingDelay = 0;
SysTick的中断函数在stm32f10x_it.c中定义,定义代码为
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
TimingDelay--;
}
其中变量TimingDelay要在stm32f10x_it.c文件的开头部分进行定义,定义代码为
extern uint32_t TimingDelay;
表明变量TimingDelay的定义在其他文件中已经有了,在这里进行引申使用。
SysTick的中断函数可以自己添加一些定时变量,当执行中断函数时会对这些变量进行运算。一般为自减运算,当变量为零时表明相应的时间到达,然后可以重新赋值并做出相应的处理。运用方式和延时函数中的变量TimingDelay一样,都需要在两个文件中定义。这样可以解决因为延时过多而造成芯片性能的降低,在按键判断中的效果比较显著。需要注意的是在中断函数中对变量最好直接进行自减,不需要任何的判断。如果有判断的话,会导致判断中的代码无法执行,造成不理想的结果。
stm32f10x_it.c文件中也有其他模块的中断函数的定义,但都是不完全定义。在使用时需要对相应的中断函数进行编写。
独立按键讲解
蓝桥杯嵌入式的独立按键只有四个(复位按键除外)。所以可以直接判断这四个按键对应I/O口的高低电平就可以直接使用。这四个独立按键的电路图为
对应的I/O接口为
及
B1—PA0
B2—PA8
B3—PB1
B4—PB2
独立按键的初始化函数为
/**
* @说明 按键接口初始化函数
* @参数 none
* @返回值 None
*/
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//B1、B2按键引脚配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//B3、B4按键引脚配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
需要注意的是GPIO口的模式为上拉输入,不能为其它的模式。所以当对应的I/O口为低电平的时候,表明该按键被按下。
按键扫描函数为
/**
* @说明 按键扫描函数
* @参数 none
* @返回值 None
*/
uint8_t Key_Scan(void)
{
uint8_t key_value = 0xff;
if(RB1 == 0){
key_value = '1';
}
if(RB2 == 0){
key_value = '2';
}
if(RB3 == 0){
key_value = '3';
}
if(RB4 == 0){
key_value = '4';
}
return key_value;
}
其中RB1、RB2、RB3、RB4可在文件开头定义为
#define RB1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define RB2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define RB3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define RB4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
函数GPIO_ReadInputDataBit为读取相应I/O口的电平,由参数确定是哪个I/O口。函数GPIO_ReadInputDataBit的定义在stm32f10x_gpio.c中的第281行,声明在stm32f10x_gpio.h中的第353行。其参数与I/O口初始化参数一样。如果忘了可以参考蓝桥杯嵌入式之LED讲解(点击文字可以跳转到相应的推文)。
扫描函数的返回值为字符型,不是数字1、2、3、4的数值。在按键判断的时候要特别注意!!!