[CW32L083系列] LCD计数器

[复制链接]
1963|9
 楼主| lulugl 发表于 2023-6-18 08:28 | 显示全部楼层 |阅读模式
本帖最后由 lulugl 于 2023-6-18 08:28 编辑

【目的】实现一个计数器,按下按键1开始计时,再次按下按键1实现暂停,再次按下,继续计时。按下按键2实现清零。
【实现步骤】
1、初始化时钟,代码如下:
  1. void RCC_Configuration(void)
  2. {
  3.     /* 0. HSI使能并校准 */
  4. //  RCC_HSI_OUT();
  5.     RCC_HSI_Enable(RCC_HSIOSC_DIV6);

  6.     /* 1. 设置HCLK和PCLK的分频系数 */
  7.     RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
  8.     RCC_PCLKPRS_Config(RCC_PCLK_DIV1);

  9. //  RCC_HCLK_OUT();

  10. //   __breakpoint(0);

  11.     /* 2. 使能PLL,通过HSI倍频到64MHz */
  12.     RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, RCC_PLL_MUL_8); // HSI 默认输出频率8MHz
  13. //  RCC_PLL_OUT();

  14.     ///< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle
  15.     ///< 当使用的时钟源HCLK大于48M,小于等于72MHz:设置FLASH 读等待周期为3 cycle
  16.     __RCC_FLASH_CLK_ENABLE();
  17.     FLASH_SetLatency(FLASH_Latency_3);

  18.     /* 3. 时钟切换到PLL */
  19.     RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL);
  20.     RCC_SystemCoreClockUpdate(64000000);

  21.     /* 4. 配置外设时钟 */
  22. //  __RCC_GPIOF_CLK_ENABLE();
  23. //  __RCC_GPIOE_CLK_ENABLE();
  24. //  __RCC_GPIOD_CLK_ENABLE();
  25. //  __RCC_GPIOC_CLK_ENABLE();
  26. //  __RCC_GPIOB_CLK_ENABLE();
  27. //  __RCC_GPIOA_CLK_ENABLE();
  28. //  __RCC_LCD_CLK_ENABLE();

  29. }
2. 初始化按键
板载按键1为PA4,按键2为PA5,根据原理图,都接了上位电阻,所以需要配置为下拉中断触发。
  1. void GPIO_Configuration(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStruct = {0};

  4.     /* 配置PA4、PA5为按键输入 */

  5.     GPIO_InitStruct.IT = GPIO_IT_FALLING;
  6.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  7.     GPIO_InitStruct.Pins = GPIO_PIN_4 | GPIO_PIN_5;

  8.     __RCC_GPIOA_CLK_ENABLE();
  9.     GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
  10. }


3、中断配置
  1. void NVIC_Configuration(void)
  2. {
  3.     __disable_irq();
  4. //  NVIC_EnableIRQ(WDT_IRQn);
  5.     NVIC_SetPriority(GPIOA_IRQn, 0);
  6. //  NVIC_SetPriority(SysTick_IRQn, 1);
  7.     NVIC_EnableIRQ(GPIOA_IRQn);
  8.     __enable_irq();
  9. }
4、中断回调函数,在中断回调中只清除中断标志,业务处理在主函数中处理:
  1. /**
  2. * [url=home.php?mod=space&uid=247401]@brief[/url] This funcation handles GPIOA
  3. */
  4. void GPIOA_IRQHandler(void)
  5. {

  6.                 CW_GPIOA->ICR = 0; //清除中断标志

  7. }
5、LCD驱动
在LCD驱动中,我们初始化LCD(具体见官方示例),然后是书写LCD数字显示驱动,具体代码如下:
  1. #include "lcd.h"
  2. //      7              6              5            4      3           2              1                         0
  3. // RAM01  RAM00   RAM03  RAM02   RAM801  RAM10                                   RAM13  RAM12              RAM92  RAM91




  4. /*  段码低8(左) */
  5. static uint8_t num_L[10] = {
  6.         0x0d, //0
  7.         0x00, //1
  8.         0x0e, //2
  9.         0x0a, //3
  10.         0x03, //4
  11.         0x0b,  //5
  12.         0x0f,  //6
  13.         0x00,  //7
  14.         0x0f,  //8
  15.         0x0b,  //9
  16. };
  17. /*  段码高8(右) */
  18. static uint8_t num_H[10] = {
  19.         0x07,
  20.         0x06,
  21.         0x03,
  22.         0x07,//3
  23.         0x06,//4
  24.         0x05, //5
  25.         0x05, //
  26.         0x07, //7
  27.         0x07, //8
  28.         0x07, //9
  29. };
  30. void show_nums(uint32_t num)
  31. {
  32.         uint8_t i=0;
  33.         uint8_t j;
  34.         uint32_t temp;
  35.         temp = num;
  36.         //空显示
  37.         CW_LCD->RAM0 = 0;
  38.   CW_LCD->RAM1 = 0;
  39.   CW_LCD->RAM8 = 0;
  40.   CW_LCD->RAM9 = 0;
  41.         if(temp == 0)
  42.                 show_num(0,0);
  43.         while(temp>0)
  44.         {
  45.                 j = temp%10;
  46.                 show_num(i,j);
  47.                 temp /=10;
  48.                 i++;
  49.         }
  50. }


  51. void show_num(uint8_t wei, uint8_t num)
  52. {

  53.         switch(wei)
  54.         {
  55.                 case 7:
  56.                 {
  57.                                 //显示第7个数码管
  58.                         CW_LCD->RAM0 |= num_H[num]<<8 | num_L[num];
  59.                         
  60.                         break;
  61.                 }
  62.                 case 6:
  63.                 {
  64.                         //显示第6个数码管
  65.                         CW_LCD->RAM0 |= (num_H[num]<<8 | num_L[num]) <<16;
  66.                         break;
  67.                 }
  68.                 case 5:
  69.                 {
  70.                         //显示第5个数码管
  71.                         CW_LCD->RAM1 |= num_L[num];
  72.                         CW_LCD->RAM8 |= num_H[num];
  73.                         break;
  74.                 }
  75.                 case 4:
  76.                 {
  77.                         //显示第4个数码管
  78.                         CW_LCD->RAM8 |= num_H[num]<<16 | num_L[num]<<8;
  79.                         break;
  80.                 }
  81.                 case 3:
  82.                 {
  83.                         //显示第3个数码管
  84.                         CW_LCD->RAM8 |= num_L[num]<<24;
  85.       CW_LCD->RAM9 |= num_H[num];
  86.                         break;
  87.                 }
  88.                 case 2:
  89.                 {
  90.                         //显示第2个数码管
  91.                         CW_LCD->RAM9 |= num_H[num]<<16 | num_L[num]<<8;
  92.                         break;
  93.                 }
  94.                 case 1:
  95.                 {
  96.                         //显示第1个数码管
  97.                         CW_LCD->RAM1 |= num_H[num]<<8;
  98.                         CW_LCD->RAM9 |= num_L[num]<<24;
  99.                         break;
  100.                 }
  101.                 case 0:
  102.                 {
  103.                         //显示第0个数码管
  104.                         CW_LCD->RAM1 |= num_H[num]<<24 | num_L[num]<<16;
  105.                         break;
  106.                 }
  107.         }
  108.                                 
  109. }

  110. void LCD_Configuration(void)
  111. {
  112.     LCD_InitTypeDef LCD_InitStruct = {0};

  113.     LCD_InitStruct.LCD_Bias = LCD_Bias_1_3;
  114.     LCD_InitStruct.LCD_ClockSource = LCD_CLOCK_SOURCE_LSI;
  115.     LCD_InitStruct.LCD_Duty = LCD_Duty_1_4;
  116.     LCD_InitStruct.LCD_ScanFreq = LCD_SCAN_FREQ_256HZ;
  117.     LCD_InitStruct.LCD_VoltageSource = LCD_VoltageSource_Internal;

  118.     __RCC_LCD_CLK_ENABLE();
  119.     RCC_LSI_Enable();
  120.     LCD_Init(&LCD_InitStruct);     //基本配置
  121.     // BTL004 LCD 对应的连接
  122.     //PA12 COM3
  123.     //PA11 COM2
  124.     //PA10 COM1
  125.     //PA09 COM0
  126.     //PA08 SEG0
  127.     //PC09 SEG1
  128.     //PC08 SEG2
  129.     //PC07 SEG3
  130.     //PC06 SEG4
  131.     //PD15 SEG32
  132.     //PD14 SEG33
  133.     //PD13 SEG34
  134.     //PD12 SEG35
  135.     //PD11 SEG36
  136.     //PD10 SEG37
  137.     //PD09 SEG38
  138.     //PD08 SEG39
  139.     //PB15 SEG5
  140.     //PB14 SEG6
  141.     //PB13 SEG7
  142.     // 分配引脚
  143.     LCD_COMConfig(LCD_COM0 | LCD_COM1 | LCD_COM2 | LCD_COM3, ENABLE);
  144.     LCD_SEG0to23Config(0x0000FF, ENABLE);
  145.     LCD_SEG32to55Config(0x0000FF,ENABLE);



  146.     CW_LCD->RAM[0] = 0;
  147.     CW_LCD->RAM[1] = 0;
  148.     CW_LCD->RAM2 = 0;
  149.     CW_LCD->RAM3 = 0;
  150.     CW_LCD->RAM4 = 0;
  151.     CW_LCD->RAM5 = 0;
  152.     CW_LCD->RAM6 = 0;
  153.     CW_LCD->RAM7 = 0;
  154.     CW_LCD->RAM8 = 0;
  155.     CW_LCD->RAM9 = 0;
  156.     CW_LCD->RAM10 = 0;
  157.     CW_LCD->RAM11 = 0;
  158.     CW_LCD->RAM12 = 0;
  159.     CW_LCD->RAM13 = 0;

  160.     LCD_Cmd(ENABLE);
  161.     CW_LCD->RAM0 = 0x0f0f;
  162.     LCD_ContrastConfig(LCD_Contrast_Level_2);
  163.     LCD_DriveVoltageConfig(LCD_INRS_LEVEL_0);
  164. }
5、主函数中,我们检查按键1、按键2,并做出相应的处理。具体代码如下:
  1. #include "main.h"
  2. void NVIC_Configuration(void);
  3. void RCC_Configuration(void);
  4. uint8_t Key1Count = 0;
  5. uint8_t Key2Count = 0;
  6. int32_t main(void)
  7. {
  8.     uint32_t show_conut=0;
  9.                 uint32_t time_count = 0;
  10.         
  11.     CW_SYSCTRL->AHBEN_f.GPIOC = 1U;    //Open GPIOA Clk

  12.     CW_GPIOC->ANALOG_f.PIN2 = 0U;      //Digital
  13.     CW_GPIOC->BRR_f.BRR2 = 1U;         //Reset PA00
  14.     CW_GPIOC->DIR_f.PIN2 = 0U;         //Output
  15.                 RCC_Configuration();
  16.                 GPIO_Configuration();
  17.                 NVIC_Configuration();
  18.                 LCD_Configuration();
  19.           show_nums(show_conut);
  20.     while(1)
  21.     {
  22.         
  23.                         if(PA04_GETVALUE() == 0)
  24.         {
  25.                                         FirmwareDelay( 20000 );
  26.                                         if(PA04_GETVALUE() == 0)
  27.                                         {
  28.             Key1Count++;
  29.                                         }
  30.         }
  31.                         if(PA05_GETVALUE() == 0)
  32.         {
  33.                                         FirmwareDelay( 20000 );
  34.                                         if(PA05_GETVALUE() == 0)
  35.                                         {
  36.             Key2Count++;
  37.                                         }
  38.         }
  39.                                 //如果按下2暂停显示
  40.                         if(Key1Count == 2 )
  41.                         {
  42.                                 Key1Count=0;
  43.                         }
  44.                         //按下K2清零,停止显示
  45.                         if(Key2Count==1)
  46.                         {
  47.                                 show_conut = 0;
  48.                                 Key1Count = 0;
  49.                                 Key2Count = 0;
  50.                                 show_nums(show_conut);
  51.                         }
  52.                         FirmwareDelay( 200 );
  53.                         time_count ++;
  54.                         if(time_count > 1000)
  55.                         {
  56.                                 time_count = 1;
  57.                                 //如果按下1开始显示
  58.                                 if(Key1Count ==1)
  59.                                 {
  60.                                         show_conut ++;
  61.                                         show_nums(show_conut);
  62.                                 }
  63.                                 //溢出清零
  64.                                 if(show_conut==65535)
  65.                                 {
  66.                                         show_conut=0;
  67.                                 }
  68.                                 //翻转LED1
  69.                                 CW_GPIOC->TOG = bv2;
  70.                         }

  71.     }

  72. }

具体效果见视频:
附工程代码: mypro_LCD.zip (358.76 KB, 下载次数: 5)
tpgf 发表于 2023-7-7 11:46 | 显示全部楼层
如果一直没有重新计时而超出数据范围了怎么办呢
wowu 发表于 2023-7-7 12:18 | 显示全部楼层
超过计数值的数据范围的时候会有报警的措施吗
 楼主| lulugl 发表于 2023-7-7 12:39 | 显示全部楼层
wowu 发表于 2023-7-7 12:18
超过计数值的数据范围的时候会有报警的措施吗

这个可以自己设置。可以实现的!
paotangsan 发表于 2023-7-7 12:40 | 显示全部楼层
如果一直计时下去而不复位或者清零 那么需要有一个溢出情况的处理函数吧
xiaoqizi 发表于 2023-7-7 13:45 | 显示全部楼层
这种根据按键来进行操作的代码里边是不是需要添加防抖啊
 楼主| lulugl 发表于 2023-7-7 17:23 | 显示全部楼层
xiaoqizi 发表于 2023-7-7 13:45
这种根据按键来进行操作的代码里边是不是需要添加防抖啊

对,要加
renzheshengui 发表于 2023-7-7 18:05 | 显示全部楼层
这个计数器有没有实际中的用处呢 还是就是用来练习计数器以及io的操作呢
wakayi 发表于 2023-7-7 18:37 | 显示全部楼层
清零的同时是停止计时还是从零开始继续计时呢
szt1993 发表于 2023-7-11 22:00 | 显示全部楼层
wakayi 发表于 2023-7-7 18:37
清零的同时是停止计时还是从零开始继续计时呢

楼主暂停和清0是分别控制的,清零后是暂停的,开始后才开始
您需要登录后才可以回帖 登录 | 注册

本版积分规则

188

主题

843

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部