实验:要求完成码表,具体要求如下:
要求:显示格式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口 |
A1 | PB2 |
A2 | PB3 |
A3 | PB4 |
A4 | PB5 |
a | PE0 |
b | PE1 |
c | PE2 |
d | PE3 |
e | PE4 |
f | PE5 |
g | PE6 |
dp | PC13 |
通过上述电路图可知,数码管为共阳极数码管,PB2-PB5低电平选中数码管,其中,注意:PB3和PB3引脚默认状态下不是普通的IO口,所以需要用到其复用功能:
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 开启服用引脚时钟,保证引脚第二功能正常使用
- GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG,使能SWD
数码管为共阳极数码管,其编码为:
- // 共阳极编码 0-9 a- f
- unsigned char seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
接下来是按键的截下图,如下:
引脚对应关系:
按键 | STM32 的IO引脚 |
KEY1 | PC0 |
KEY2 | PC1 |
KEY3 | PC2 |
KEY4 | PC3 |
KEY5 | PC4 |
接下来依据任务要求完成代码:
按键初始化:
- /********************************************
- 函数名称:void KeyInit(void)
- 函数参数:无参,返回值为空
- 函数功能:实现按键功能初始化
- 作者:***
- 时间:2022.3.8
- 修改作者:
- 修改实现:
- 修改说明:
- *********************************************/
- void KeyInit(void)
- {
- // KEY接在PC0-PC4上,一共5个按键
- //初始化步骤
- /**
- 1.开启所对应的时钟
- 2.选择所需要的IO口
- 3.设置IO口的工作模式
- 4.初始化上述配置
- **/
- GPIO_InitTypeDef GPIO_InitStruct; // 结构体变量申明
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 开启时钟
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
- |GPIO_Pin_4; // 选择PC0-PC4口
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式
-
- GPIO_Init(GPIOC,&GPIO_InitStruct); // 配置初始化
-
- }
数码管初始化:
- /********************************************
- 函数名称:void SegInit(void)
- 函数参数:无参,返回值为空
- 函数功能:实现数码管初始化
- 作者:***
- 时间:2022.3.17
- 修改作者:
- 修改实现:
- 修改说明:
- *********************************************/
- void SegInit(void)
- {
- //初始化步骤
- /**
- 1.开启所对应的时钟
- 2.选择所需要的IO口
- 3.设置IO口的工作模式
- 4.设置IO的输出速率(当IO口设置成输出模式才需要)
- 5.初始化上述配置
- 6.初始化IO的初值
- **/
- GPIO_InitTypeDef GPIO_InitStruct; // 结构体变量申明
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 开启时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 开启时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); // 开启时钟
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 开启服用引脚时钟,保证引脚第二功能正常使用
-
- GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG,使能SWD
-
- // 设置片选引脚
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; // 选择PB2-PB5口
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速率50MHz
- GPIO_Init(GPIOB,&GPIO_InitStruct); // 配置初始化
-
- // 设置七段引脚
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
- |GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; // 选择PE0-PE6口
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速率50MHz
- GPIO_Init(GPIOE,&GPIO_InitStruct); // 配置初始化
-
- // 设置DP(小数点)引脚
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; // 选择PE0-PE6口
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速率50MHz
- GPIO_Init(GPIOC,&GPIO_InitStruct); // 配置初始化
-
- GPIO_Write(GPIOE, 0X007F); // 设置七段引脚为高电平 0111 1111
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点
- GPIO_WriteBit(GPIOB,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5,Bit_SET); // 设置片选引脚为高电平
-
- }
定时器中断服务函数:
- /********************************************
- 函数名称:TIM4_IRQHandler(void)
- 函数参数:
- 无参,无返回参数
- 函数功能:定时器定时10ms
- 作者:***
- 时间:2022.5.19
- 修改作者:
- 修改时间:
- 修改说明:
- 修改作者:
- 修改时间:
- 修改说明:
- *********************************************/
- void TIM4_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM4, TIM_IT_Update) == 1) // 标志计数溢出中断产生
- {
- tim4Cnt++; // 秒统计
- if(tim4Cnt>9999) // 99:99 99*100+99
- {
- tim4Cnt = 0;
- }
- }
- TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
- }
按键功能实现:
- /********************************************
- 函数名称:int KeyScan6(void)
- 函数参数:无
- 函数功能:要求:显示格式XX.YY。
- 按键1可控制计数暂停还是启动
- 按键2 清零(必需在暂停后才可以操作)
- 按键3 存储当前码表的时间,存储成功后显示y
- 按键4 显示存储的码表时间
- 按键5 记录的码表时间向下翻页
- 作者:***
- 时间:2022.5.19
- 修改作者:
- 修改实现:
- 修改说明:
- *********************************************/
- void KeyScan6(void)
- {
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0 ) // 判断按键是否按下
- {
- delay_ms(10); // 消抖
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0 )
- {
- flag = -1*flag; // -1和1跳转
- }
- while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0);
- }
- if(1 == flag) // 计数
- {
- TIM_Cmd(TIM4,ENABLE);
- }
- if(-1 == flag) // 暂停
- {
- TIM_Cmd(TIM4,DISABLE); // 关闭定时器
-
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0 ) // 判断按键是否按下
- {
- delay_ms(10); // 消抖
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0 )
- {
- tim4Cnt = 0; // 在暂停的条件下实现码表清0
- }
- while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0);
- }
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0 ) // 判断按键是否按下
- {
- delay_ms(10); // 消抖
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0 )
- {
- saveTime[key3Cnt] = tim4Cnt;
- key3Cnt++; // 按键按下次数统计
- if(key3Cnt>9)
- {
- key3Cnt = 0; // 计数归0
- }
- //SegDis10(); // 显示y
- }
- while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0) // 按键松开检查
- {
- SegDis10(); // 显示y
- }
- }
-
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0 ) // 判断按键是否按下
- {
- delay_ms(10); // 消抖
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0 )
- {
- tim4Cnt = saveTime[0];
- }
- while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0); // 按键松开检查
- }
-
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0 ) // 判断按键是否按下
- {
- delay_ms(10); // 消抖
- if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0 )
- {
- key5Cnt++; // 按键按下计数
- if(key5Cnt>9)
- {
- key5Cnt = 0; // 归0
- }
- tim4Cnt = saveTime[key5Cnt];
- }
- while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0); // 按键松开检查
- }
- }
-
- SegDis9();
- }
数码管功能实现:
-
- /********************************************
- 函数名称:void SegDis9(int value)
- 函数参数:无参,返回值为空
- 函数功能:
- 要求:显示格式XX.YY。
- 作者:***
- 时间:2022.5.17
- 修改作者:
- 修改实现:
- 修改说明:
- *********************************************/
- void SegDis9(void)
- {
-
- // 数码管a
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
- GPIO_Write(GPIOE, seg[tim4Cnt/1000]); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- // 数码管b
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_RESET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
- GPIO_Write(GPIOE, seg[tim4Cnt/100%10]); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET); // 小数点不需要显示
- delay_ms(5);
- // 数码管c
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_RESET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
- GPIO_Write(GPIOE, seg[tim4Cnt/10%10]); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- // 数码管d
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET); //
- GPIO_Write(GPIOE, seg[tim4Cnt%10]); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- }
-
- /********************************************
- 函数名称:void SegDis10(int value)
- 函数参数:无参,返回值为空
- 函数功能:
- 要求:y。
- 共阳极编码y的值:0X91
- 作者:***
- 时间:2022.5.17
- 修改作者:
- 修改实现:
- 修改说明:
- *********************************************/
- void SegDis10(void)
- {
- // 数码管a
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
- GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- // 数码管b
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_RESET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
- GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- // 数码管c
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_RESET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //
- GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- // 数码管d
- GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET); //
- GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET); //
- GPIO_Write(GPIOE, 0X91); // 可以实现多位写入
- GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET); // 小数点不需要显示
- delay_ms(5);
- }
实现效果:
源码下载地址:定时器实现码表(数码管显示)-C文档类资源-CSDN文库