本帖最后由 lulugl 于 2023-6-18 08:28 编辑
【目的】实现一个计数器,按下按键1开始计时,再次按下按键1实现暂停,再次按下,继续计时。按下按键2实现清零。
【实现步骤】
1、初始化时钟,代码如下:
- void RCC_Configuration(void)
- {
- /* 0. HSI使能并校准 */
- // RCC_HSI_OUT();
- RCC_HSI_Enable(RCC_HSIOSC_DIV6);
- /* 1. 设置HCLK和PCLK的分频系数 */
- RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
- RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
- // RCC_HCLK_OUT();
- // __breakpoint(0);
- /* 2. 使能PLL,通过HSI倍频到64MHz */
- RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, RCC_PLL_MUL_8); // HSI 默认输出频率8MHz
- // RCC_PLL_OUT();
- ///< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle
- ///< 当使用的时钟源HCLK大于48M,小于等于72MHz:设置FLASH 读等待周期为3 cycle
- __RCC_FLASH_CLK_ENABLE();
- FLASH_SetLatency(FLASH_Latency_3);
- /* 3. 时钟切换到PLL */
- RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL);
- RCC_SystemCoreClockUpdate(64000000);
- /* 4. 配置外设时钟 */
- // __RCC_GPIOF_CLK_ENABLE();
- // __RCC_GPIOE_CLK_ENABLE();
- // __RCC_GPIOD_CLK_ENABLE();
- // __RCC_GPIOC_CLK_ENABLE();
- // __RCC_GPIOB_CLK_ENABLE();
- // __RCC_GPIOA_CLK_ENABLE();
- // __RCC_LCD_CLK_ENABLE();
- }
2. 初始化按键
板载按键1为PA4,按键2为PA5,根据原理图,都接了上位电阻,所以需要配置为下拉中断触发。
- void GPIO_Configuration(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- /* 配置PA4、PA5为按键输入 */
- GPIO_InitStruct.IT = GPIO_IT_FALLING;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pins = GPIO_PIN_4 | GPIO_PIN_5;
- __RCC_GPIOA_CLK_ENABLE();
- GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
- }
3、中断配置
- void NVIC_Configuration(void)
- {
- __disable_irq();
- // NVIC_EnableIRQ(WDT_IRQn);
- NVIC_SetPriority(GPIOA_IRQn, 0);
- // NVIC_SetPriority(SysTick_IRQn, 1);
- NVIC_EnableIRQ(GPIOA_IRQn);
- __enable_irq();
- }
4、中断回调函数,在中断回调中只清除中断标志,业务处理在主函数中处理:
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] This funcation handles GPIOA
- */
- void GPIOA_IRQHandler(void)
- {
- CW_GPIOA->ICR = 0; //清除中断标志
- }
5、LCD驱动
在LCD驱动中,我们初始化LCD(具体见官方示例),然后是书写LCD数字显示驱动,具体代码如下:
- #include "lcd.h"
- // 7 6 5 4 3 2 1 0
- // RAM01 RAM00 RAM03 RAM02 RAM801 RAM10 RAM13 RAM12 RAM92 RAM91
- /* 段码低8(左) */
- static uint8_t num_L[10] = {
- 0x0d, //0
- 0x00, //1
- 0x0e, //2
- 0x0a, //3
- 0x03, //4
- 0x0b, //5
- 0x0f, //6
- 0x00, //7
- 0x0f, //8
- 0x0b, //9
- };
- /* 段码高8(右) */
- static uint8_t num_H[10] = {
- 0x07,
- 0x06,
- 0x03,
- 0x07,//3
- 0x06,//4
- 0x05, //5
- 0x05, //
- 0x07, //7
- 0x07, //8
- 0x07, //9
- };
- void show_nums(uint32_t num)
- {
- uint8_t i=0;
- uint8_t j;
- uint32_t temp;
- temp = num;
- //空显示
- CW_LCD->RAM0 = 0;
- CW_LCD->RAM1 = 0;
- CW_LCD->RAM8 = 0;
- CW_LCD->RAM9 = 0;
- if(temp == 0)
- show_num(0,0);
- while(temp>0)
- {
- j = temp%10;
- show_num(i,j);
- temp /=10;
- i++;
- }
- }
- void show_num(uint8_t wei, uint8_t num)
- {
- switch(wei)
- {
- case 7:
- {
- //显示第7个数码管
- CW_LCD->RAM0 |= num_H[num]<<8 | num_L[num];
-
- break;
- }
- case 6:
- {
- //显示第6个数码管
- CW_LCD->RAM0 |= (num_H[num]<<8 | num_L[num]) <<16;
- break;
- }
- case 5:
- {
- //显示第5个数码管
- CW_LCD->RAM1 |= num_L[num];
- CW_LCD->RAM8 |= num_H[num];
- break;
- }
- case 4:
- {
- //显示第4个数码管
- CW_LCD->RAM8 |= num_H[num]<<16 | num_L[num]<<8;
- break;
- }
- case 3:
- {
- //显示第3个数码管
- CW_LCD->RAM8 |= num_L[num]<<24;
- CW_LCD->RAM9 |= num_H[num];
- break;
- }
- case 2:
- {
- //显示第2个数码管
- CW_LCD->RAM9 |= num_H[num]<<16 | num_L[num]<<8;
- break;
- }
- case 1:
- {
- //显示第1个数码管
- CW_LCD->RAM1 |= num_H[num]<<8;
- CW_LCD->RAM9 |= num_L[num]<<24;
- break;
- }
- case 0:
- {
- //显示第0个数码管
- CW_LCD->RAM1 |= num_H[num]<<24 | num_L[num]<<16;
- break;
- }
- }
-
- }
- void LCD_Configuration(void)
- {
- LCD_InitTypeDef LCD_InitStruct = {0};
- LCD_InitStruct.LCD_Bias = LCD_Bias_1_3;
- LCD_InitStruct.LCD_ClockSource = LCD_CLOCK_SOURCE_LSI;
- LCD_InitStruct.LCD_Duty = LCD_Duty_1_4;
- LCD_InitStruct.LCD_ScanFreq = LCD_SCAN_FREQ_256HZ;
- LCD_InitStruct.LCD_VoltageSource = LCD_VoltageSource_Internal;
- __RCC_LCD_CLK_ENABLE();
- RCC_LSI_Enable();
- LCD_Init(&LCD_InitStruct); //基本配置
- // BTL004 LCD 对应的连接
- //PA12 COM3
- //PA11 COM2
- //PA10 COM1
- //PA09 COM0
- //PA08 SEG0
- //PC09 SEG1
- //PC08 SEG2
- //PC07 SEG3
- //PC06 SEG4
- //PD15 SEG32
- //PD14 SEG33
- //PD13 SEG34
- //PD12 SEG35
- //PD11 SEG36
- //PD10 SEG37
- //PD09 SEG38
- //PD08 SEG39
- //PB15 SEG5
- //PB14 SEG6
- //PB13 SEG7
- // 分配引脚
- LCD_COMConfig(LCD_COM0 | LCD_COM1 | LCD_COM2 | LCD_COM3, ENABLE);
- LCD_SEG0to23Config(0x0000FF, ENABLE);
- LCD_SEG32to55Config(0x0000FF,ENABLE);
- CW_LCD->RAM[0] = 0;
- CW_LCD->RAM[1] = 0;
- CW_LCD->RAM2 = 0;
- CW_LCD->RAM3 = 0;
- CW_LCD->RAM4 = 0;
- CW_LCD->RAM5 = 0;
- CW_LCD->RAM6 = 0;
- CW_LCD->RAM7 = 0;
- CW_LCD->RAM8 = 0;
- CW_LCD->RAM9 = 0;
- CW_LCD->RAM10 = 0;
- CW_LCD->RAM11 = 0;
- CW_LCD->RAM12 = 0;
- CW_LCD->RAM13 = 0;
- LCD_Cmd(ENABLE);
- CW_LCD->RAM0 = 0x0f0f;
- LCD_ContrastConfig(LCD_Contrast_Level_2);
- LCD_DriveVoltageConfig(LCD_INRS_LEVEL_0);
- }
5、主函数中,我们检查按键1、按键2,并做出相应的处理。具体代码如下:
- #include "main.h"
- void NVIC_Configuration(void);
- void RCC_Configuration(void);
- uint8_t Key1Count = 0;
- uint8_t Key2Count = 0;
- int32_t main(void)
- {
- uint32_t show_conut=0;
- uint32_t time_count = 0;
-
- CW_SYSCTRL->AHBEN_f.GPIOC = 1U; //Open GPIOA Clk
- CW_GPIOC->ANALOG_f.PIN2 = 0U; //Digital
- CW_GPIOC->BRR_f.BRR2 = 1U; //Reset PA00
- CW_GPIOC->DIR_f.PIN2 = 0U; //Output
- RCC_Configuration();
- GPIO_Configuration();
- NVIC_Configuration();
- LCD_Configuration();
- show_nums(show_conut);
- while(1)
- {
-
- if(PA04_GETVALUE() == 0)
- {
- FirmwareDelay( 20000 );
- if(PA04_GETVALUE() == 0)
- {
- Key1Count++;
- }
- }
- if(PA05_GETVALUE() == 0)
- {
- FirmwareDelay( 20000 );
- if(PA05_GETVALUE() == 0)
- {
- Key2Count++;
- }
- }
- //如果按下2暂停显示
- if(Key1Count == 2 )
- {
- Key1Count=0;
- }
- //按下K2清零,停止显示
- if(Key2Count==1)
- {
- show_conut = 0;
- Key1Count = 0;
- Key2Count = 0;
- show_nums(show_conut);
- }
- FirmwareDelay( 200 );
- time_count ++;
- if(time_count > 1000)
- {
- time_count = 1;
- //如果按下1开始显示
- if(Key1Count ==1)
- {
- show_conut ++;
- show_nums(show_conut);
- }
- //溢出清零
- if(show_conut==65535)
- {
- show_conut=0;
- }
- //翻转LED1
- CW_GPIOC->TOG = bv2;
- }
- }
- }
具体效果见视频:
附工程代码:
mypro_LCD.zip
(358.76 KB, 下载次数: 5)
|