为了验证GD32F130C8与ST的兼容性,版主本次做了按键扫描的实验。
本次实验使用GD32130C-START的开发板,其按键连接PA0引脚,并通过上拉电阻与电容来做硬件消抖与EMI去除。
在软件上面,仍然使用STM32F0xx的固件库。版主以STM32F030为基准型号生成固件库,并放入IAR软件里调用。
软件架构实现方式:
首先,使用库函数的方式初始化了芯片的晶振系统,使用其外置的8MHz晶振。
然后初始化了板载外设,两个LED灯与1个按键;
在板载bsp支持包内添加按键扫描功能函数,其函数具体实现请看版主的源代码;
在应用层上面设计了按键扫描的检测函数,通过状态机的方式来实现按键的各个状态之间的流轮。状态图版主这里因为时间关系没有画,也请大家直接看源代码,毕竟代码量较少,还是相当容易就能看出来的。
实验现象:当有按键按下时,LED0灯将会亮起,按键释放后,LED1灯将会熄灭;
实验结果:实验结果与设计方案完全相符,STM32F0xx的固件库目前完美支持GD32F130C8芯片。
版主源代码如下:
void SysClockInit(void)
{
ErrorStatus HSEStartUpStatus;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if (HSEStartUpStatus == SUCCESS)
{
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(ENABLE);
/* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_0);
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLKConfig(RCC_HCLK_Div1);
/* PLLCLK = 8MHz * 6 = 48 MHz */
// RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* 此处需要根据外部晶振的改变而改变 */
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_12); /* Max Freq = 48MHz */
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock configuration.
User can add here some code to deal with this error */
/* Go to infinite loop */
while (1)
{
}
}
}
/**
* @brief 初始化按键 PA0
* @param
* @retval
* @date 2015-03-26
* @note 外部连接上拉电阻,空闲状态为高电压,按下时为低电压
*/
void KeyInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* Configure PA0 in input pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**
* @brief scan key
* @param the key number
* @retval true = press down; false = idle;
* @date 2015-03-28
* @note PA0 =>外部连接上拉电阻,空闲状态为高电压,按下时为低电压
*/
bool KeyScan(uint8_t num)
{
bool keyStatus = false;
uint16_t t;
t = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
switch(num)
{
case 0:
{
if(GPIO_Pin_0 == (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)))
{
keyStatus = false;
}
else
{
keyStatus = true;
}
break;
}
default: keyStatus = false;
}
return keyStatus;
}
/**
* @brief led initial
* @param
* @retval
* @date 2015-03-26
* @note LED0 =>PF6 LED1 =>PF7
*/
void LedInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF, &GPIO_InitStructure);
}
/**
* @brief LED on
* @param
* @retval
* @date 2015-03-27
* @note
*/
void LedOn(uint8_t num)
{
switch(num)
{
case 0:
{
GPIO_SetBits(GPIOF, GPIO_Pin_6);
break;
}
case 1:
{
GPIO_SetBits(GPIOF, GPIO_Pin_7);
break;
}
}
}
/**
* @brief LED off
* @param
* @retval
* @date 2015-03-27
* @note
*/
void LedOff(uint8_t num)
{
switch(num)
{
case 0:
{
GPIO_ResetBits(GPIOF, GPIO_Pin_6);
break;
}
case 1:
{
GPIO_ResetBits(GPIOF, GPIO_Pin_7);
break;
}
}
}
/**
* @brief led toggle
* @param
* @retval
* @date 2015-03-28
* @note
*/
void LedToggle(uint8_t num)
{
switch(num)
{
case 0:
{
GPIOF->ODR ^= GPIO_Pin_6;
break;
}
case 1:
{
GPIOF->ODR ^= GPIO_Pin_7;
break;
}
}
}
/**
* @brief bsp initial
* @param
* @retval
* @date 2015-03-26
* @note 1 *key; 1 *LED
*/
void bspInit(void)
{
SysClockInit();
LedInit();
KeyInit();
}
/**
* @brief key check
* @param
* @retval
* @date 2015-03-28
* @note
*/
void KeyCheck(void)
{
bool KeyStatus;
KeyStatus = KeyScan(0);
switch(gKeyStatus)
{
case 0: /*!< 空闲状态 */
{
if(KeyStatus == true)
{
gKeyStatus = 1;
}
else
{
gKeyStatus = 0;
LedOff(0);
}
break;
}
case 1: /*!< 消抖状态 */
{
if(KeyStatus == true)
{
gKeyCnt = 5;
gKeyStatus = 2;
}
else
{
gKeyCnt = 0;
gKeyStatus = 0;
}
break;
}
case 2: /*!< 按下状态 */
{
if(KeyStatus == true)
{
if(gKeyCnt == 0)
{
LedOn(0);
}
else
{
gKeyStatus = 2;
}
}
else
{
gKeyCnt = 0;
gKeyStatus = 0;
}
break;
}
case 3: /*!< 确认按下 */
{
LedOn(0);
break;
}
default: gKeyStatus = 0;
}
}
void main(void)
{
bool LedStatus[2];
gKeyStatus = 0;
bspInit();
gCntLed[0] = 500;
gCntLed[1] = 500;
LedStatus[0] = false;
LedStatus[1] = false;
if (SysTick_Config(48000)) //参数为系统时钟的向上溢出值,此配置为48000,即1ms中断一次
{
/* Capture error */
while (1);
}
while(1)
{
if(gCntLed[0] == 0)
{
LedToggle(1);
gCntLed[0] = 500;
}
KeyCheck();
}
}
/**
* @brief SysTick_Handler的中断入口函数
* @param
* @retval
* @date 2014-11-23
* @note
*/
void SysTick_Handler(void)
{
if(gCntLed[0] > 0)
{
gCntLed[0]--;
}
else
{
gCntLed[0] = 0;
}
if(gCntLed[1] > 0)
{
gCntLed[1]--;
}
else
{
gCntLed[1] = 0;
}
if(gKeyCnt > 0)
{
gKeyCnt--;
}
else
{
gKeyCnt = 0;
}
}
IAR工程源代码:exp02_key.zip
我要赚赏金
