• [STM32学习]定时器实现码表(数码管显示)


    实验:要求完成码表,具体要求如下:

    要求:显示格式XX.YY。
        按键1 可控制计数暂停还是启动
        按键2 清零(必需在暂停后才可以操作
        按键3 存储当前码表的时间,存储成功后显示y(必需在暂停后才可以操作
        按键4 显示存储的码表时间(必需在暂停后才可以操作
        按键5 记录的码表时间向下翻页(必需在暂停后才可以操作

    简单分析:

          码表,其实就是显示秒的下一个单位,电子手表上一般都有码表的功能,秒到分钟一般是59秒进行,而码表的下一个单位,则要计到99上才能进位到1秒,所以需要修改定时器,将定时器修改成10ms溢出中断一次,这样记录100次后就达到了1秒。

    Tim4Init(719, 999);		//	定时10ms 720*1000/72000000 = 1/100

    我们在完成实验之前一定要搞清楚它的硬件电路,分析好引脚所对应的IO口,下图为数码管硬件设计图,完全可以按照电路图设计。

    由上图可以知道,该数码管为四位八段数码管,引脚分析如下

    数码管电路STM32的IO口
    A1PB2
    A2PB3
    A3PB4
    A4PB5
    aPE0
    bPE1
    cPE2
    dPE3
    ePE4
    fPE5
    gPE6
    dpPC13

    通过上述电路图可知,数码管为共阳极数码管,PB2-PB5低电平选中数码管,其中,注意:PB3和PB3引脚默认状态下不是普通的IO口,所以需要用到其复用功能:

    1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 开启服用引脚时钟,保证引脚第二功能正常使用
    2. GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG,使能SWD

    数码管为共阳极数码管,其编码为:

    1. // 共阳极编码 0-9 a- f
    2. unsigned char seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

    接下来是按键的截下图,如下:

     引脚对应关系:

    按键STM32 的IO引脚
    KEY1PC0
    KEY2PC1
    KEY3PC2
    KEY4PC3
    KEY5PC4

    接下来依据任务要求完成代码:

    按键初始化:

    1. /********************************************
    2. 函数名称:void KeyInit(void)
    3. 函数参数:无参,返回值为空
    4. 函数功能:实现按键功能初始化
    5. 作者:***
    6. 时间:2022.3.8
    7. 修改作者:
    8. 修改实现:
    9. 修改说明:
    10. *********************************************/
    11. void KeyInit(void)
    12. {
    13. // KEY接在PC0-PC4上,一共5个按键
    14. //初始化步骤
    15. /**
    16. 1.开启所对应的时钟
    17. 2.选择所需要的IO口
    18. 3.设置IO口的工作模式
    19. 4.初始化上述配置
    20. **/
    21. GPIO_InitTypeDef GPIO_InitStruct; // 结构体变量申明
    22. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 开启时钟
    23. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
    24. |GPIO_Pin_4; // 选择PC0-PC4口
    25. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式
    26. GPIO_Init(GPIOC,&GPIO_InitStruct); // 配置初始化
    27. }

    数码管初始化:

    1. /********************************************
    2. 函数名称:void SegInit(void)
    3. 函数参数:无参,返回值为空
    4. 函数功能:实现数码管初始化
    5. 作者:***
    6. 时间:2022.3.17
    7. 修改作者:
    8. 修改实现:
    9. 修改说明:
    10. *********************************************/
    11. void SegInit(void)
    12. {
    13. //初始化步骤
    14. /**
    15. 1.开启所对应的时钟
    16. 2.选择所需要的IO口
    17. 3.设置IO口的工作模式
    18. 4.设置IO的输出速率(当IO口设置成输出模式才需要)
    19. 5.初始化上述配置
    20. 6.初始化IO的初值
    21. **/
    22. GPIO_InitTypeDef GPIO_InitStruct; // 结构体变量申明
    23. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 开启时钟
    24. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 开启时钟
    25. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); // 开启时钟
    26. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 开启服用引脚时钟,保证引脚第二功能正常使用
    27. GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG,使能SWD
    28. // 设置片选引脚
    29. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; // 选择PB2-PB5口
    30. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
    31. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速率50MHz
    32. GPIO_Init(GPIOB,&GPIO_InitStruct); // 配置初始化
    33. // 设置七段引脚
    34. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
    35. |GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; // 选择PE0-PE6口
    36. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
    37. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速率50MHz
    38. GPIO_Init(GPIOE,&GPIO_InitStruct); // 配置初始化
    39. // 设置DP(小数点)引脚
    40. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; // 选择PE0-PE6口
    41. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
    42. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速率50MHz
    43. GPIO_Init(GPIOC,&GPIO_InitStruct); // 配置初始化
    44. GPIO_Write(GPIOE, 0X007F); // 设置七段引脚为高电平 0111 1111
    45. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点
    46. GPIO_WriteBit(GPIOB,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5,Bit_SET); // 设置片选引脚为高电平
    47. }

    定时器中断服务函数:

    1. /********************************************
    2. 函数名称:TIM4_IRQHandler(void)
    3. 函数参数:
    4. 无参,无返回参数
    5. 函数功能:定时器定时10ms
    6. 作者:***
    7. 时间:2022.5.19
    8. 修改作者:
    9. 修改时间:
    10. 修改说明:
    11. 修改作者:
    12. 修改时间:
    13. 修改说明:
    14. *********************************************/
    15. void TIM4_IRQHandler(void)
    16. {
    17. if(TIM_GetITStatus(TIM4, TIM_IT_Update) == 1) // 标志计数溢出中断产生
    18. {
    19. tim4Cnt++; // 秒统计
    20. if(tim4Cnt>9999) // 99:99 99*100+99
    21. {
    22. tim4Cnt = 0;
    23. }
    24. }
    25. TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
    26. }

    按键功能实现:

    1. /********************************************
    2. 函数名称:int KeyScan6(void)
    3. 函数参数:无
    4. 函数功能:要求:显示格式XX.YY。
    5. 按键1可控制计数暂停还是启动
    6. 按键2 清零(必需在暂停后才可以操作)
    7. 按键3 存储当前码表的时间,存储成功后显示y
    8. 按键4 显示存储的码表时间
    9. 按键5 记录的码表时间向下翻页
    10. 作者:***
    11. 时间:2022.5.19
    12. 修改作者:
    13. 修改实现:
    14. 修改说明:
    15. *********************************************/
    16. void KeyScan6(void)
    17. {
    18. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0 ) // 判断按键是否按下
    19. {
    20. delay_ms(10); // 消抖
    21. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0 )
    22. {
    23. flag = -1*flag; // -1和1跳转
    24. }
    25. while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0);
    26. }
    27. if(1 == flag) // 计数
    28. {
    29. TIM_Cmd(TIM4,ENABLE);
    30. }
    31. if(-1 == flag) // 暂停
    32. {
    33. TIM_Cmd(TIM4,DISABLE); // 关闭定时器
    34. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0 ) // 判断按键是否按下
    35. {
    36. delay_ms(10); // 消抖
    37. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0 )
    38. {
    39. tim4Cnt = 0; // 在暂停的条件下实现码表清0
    40. }
    41. while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0);
    42. }
    43. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0 ) // 判断按键是否按下
    44. {
    45. delay_ms(10); // 消抖
    46. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0 )
    47. {
    48. saveTime[key3Cnt] = tim4Cnt;
    49. key3Cnt++; // 按键按下次数统计
    50. if(key3Cnt>9)
    51. {
    52. key3Cnt = 0; // 计数归0
    53. }
    54. //SegDis10(); // 显示y
    55. }
    56. while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0) // 按键松开检查
    57. {
    58. SegDis10(); // 显示y
    59. }
    60. }
    61. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0 ) // 判断按键是否按下
    62. {
    63. delay_ms(10); // 消抖
    64. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0 )
    65. {
    66. tim4Cnt = saveTime[0];
    67. }
    68. while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0); // 按键松开检查
    69. }
    70. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0 ) // 判断按键是否按下
    71. {
    72. delay_ms(10); // 消抖
    73. if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0 )
    74. {
    75. key5Cnt++; // 按键按下计数
    76. if(key5Cnt>9)
    77. {
    78. key5Cnt = 0; // 归0
    79. }
    80. tim4Cnt = saveTime[key5Cnt];
    81. }
    82. while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0); // 按键松开检查
    83. }
    84. }
    85. SegDis9();
    86. }

    数码管功能实现:

    1. /********************************************
    2. 函数名称:void SegDis9(int value)
    3. 函数参数:无参,返回值为空
    4. 函数功能:
    5. 要求:显示格式XX.YY。
    6. 作者:***
    7. 时间:2022.5.17
    8. 修改作者:
    9. 修改实现:
    10. 修改说明:
    11. *********************************************/
    12. void SegDis9(void)
    13. {
    14. // 数码管a
    15. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET); //
    16. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
    17. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
    18. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
    19. GPIO_Write(GPIOE, seg[tim4Cnt/1000]); // 可以实现多位写入
    20. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    21. delay_ms(5);
    22. // 数码管b
    23. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
    24. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_RESET); //
    25. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
    26. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
    27. GPIO_Write(GPIOE, seg[tim4Cnt/100%10]); // 可以实现多位写入
    28. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET); // 小数点不需要显示
    29. delay_ms(5);
    30. // 数码管c
    31. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
    32. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
    33. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_RESET); //
    34. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
    35. GPIO_Write(GPIOE, seg[tim4Cnt/10%10]); // 可以实现多位写入
    36. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    37. delay_ms(5);
    38. // 数码管d
    39. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
    40. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
    41. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
    42. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET); //
    43. GPIO_Write(GPIOE, seg[tim4Cnt%10]); // 可以实现多位写入
    44. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    45. delay_ms(5);
    46. }
    47. /********************************************
    48. 函数名称:void SegDis10(int value)
    49. 函数参数:无参,返回值为空
    50. 函数功能:
    51. 要求:y。
    52. 共阳极编码y的值:0X91
    53. 作者:***
    54. 时间:2022.5.17
    55. 修改作者:
    56. 修改实现:
    57. 修改说明:
    58. *********************************************/
    59. void SegDis10(void)
    60. {
    61. // 数码管a
    62. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET); //
    63. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
    64. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
    65. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
    66. GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
    67. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    68. delay_ms(5);
    69. // 数码管b
    70. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
    71. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_RESET); //
    72. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
    73. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
    74. GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
    75. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    76. delay_ms(5);
    77. // 数码管c
    78. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
    79. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
    80. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_RESET); //
    81. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
    82. GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
    83. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    84. delay_ms(5);
    85. // 数码管d
    86. GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
    87. GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
    88. GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
    89. GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET); //
    90. GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
    91. GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
    92. delay_ms(5);
    93. }

    实现效果:

    源码下载地址:定时器实现码表(数码管显示)-C文档类资源-CSDN文库

  • 相关阅读:
    shiro-登录验证
    【广州华锐互动】VR影视制片虚拟仿真教学系统
    算法必刷系列之查找、排序
    Mybatis-Plus 使用技巧与隐患
    【小尘送书-第六期】《巧用ChatGPT轻松玩转新媒体运营》AI赋能运营全流程,帮你弯道超车、轻松攀登运营之巅
    华为云云耀云服务器L实例评测|redis漏洞回顾 & MySQL数据安全解决 搭建主从集群MySQL & 相关设置
    Wlan——无线反制理论与配置讲解
    智慧工地综合管理平台-项目开发管理规范
    Docker vs. Podman: 选择容器技术的智慧之选
    MYSQL之DDL(数据库定义语言)
  • 原文地址:https://blog.csdn.net/XiaoCaiDaYong/article/details/121868439