基于正点原子STM32F1精英版秒表(库函数版)
Posted 修灯泡的老张
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于正点原子STM32F1精英版秒表(库函数版)相关的知识,希望对你有一定的参考价值。
基于正点原子STM32F1精英版秒表(库函数版)
一、前期准备
- 建立keil5文件,完成基本库函数配置;
- 本次需要的文件有:
#include "led.h" //LED灯
#include "delay.h" //延时函数
#include "key.h" //独立按键
#include "sys.h" //系统
#include "lcd.h" //TFTLCD
#include "timer.h" //定时器
#include "tpad.h" //触摸按键
#include "beep.h" //蜂鸣器
- 实现功能:
(1).秒表:按下KEU_UP开始;按下KEY1清零;按下KEY0暂停;
(2)闹钟(你要说定时炸弹我也没意见):按下触摸按键定时+1秒;
二、代码实现:
1.独立按键与触摸按键
#include "stm32f10x.h"
#include "key.h"
#include "sys.h"
#include "delay.h"
/*
KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0
KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP)
*/
//按键初始化函数
void KEY_Init(void) //IO初始化
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3;//KEY0-KEY1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4,3
//初始化 WK_UP-->GPIOA.0 下拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY3按下 WK_UP
//
u8 KEY_Scan()
static u8 key_up=1;//按键按松开标志
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
delay_ms(10);//去抖动
key_up=0;
if(KEY0==0)return KEY0_PRES;//KEY0_PRES=1
else if(KEY1==0)return KEY1_PRES;//KEY1_PRES=2
else if(WK_UP==1)return WKUP_PRES;//WKUP_PRES=3
else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;
return 0;// 无按键按下
/***********************************以上是独立按键***********************************/
//触摸按键的源程序过于繁琐,在这里就不展示了。其原理我会再出一期
2.TFTLCD
#include "lcd.h"
#include "stdlib.h"
#include "font.h"
#include "delay.h"
//在LCD上显示数字
//x,y:起点坐标
//num:数值(0~999999999);
//len:长度(即要显示的位数)
//size:字体大小
//mode:
//[7]:0,不填充;1,填充0.
//[6:1]:保留
//[0]:0,非叠加显示;1,叠加显示.
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
temp=(num/LCD_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
if(temp==0)
if(mode&0X80)LCD_ShowChar(x+(size/2)*t,y,'0',size,mode&0X01);
else LCD_ShowChar(x+(size/2)*t,y,' ',size,mode&0X01);
continue;
else enshow=1;
LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,mode&0X01);
//在LCD上显示字符串(用来显示“ :”)
//x,y:起点坐标
//width,height:区域大小
//size:字体大小
//*p:字符串起始地址
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
u8 x0=x;
width+=x;
height+=y;
while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
if(x>=width)x=x0;y+=size;
if(y>=height)break;//退出
LCD_ShowChar(x,y,*p,size,0);
x+=size/2;
p++;
3.定时器
#include "timer.h"
#include "lcd.h"
u8 hour = 0, minute = 0, second = 0, t = 0;
u16 ms=0;
void TIM3_Int_Init(u16 arr,u16 psc)
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 ENABLE 1;DISABLE 0;
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
ms++;
if(ms>99) //准备定10ms
ms=0;
second++;
if(second>59)
second=0;
minute++;
if(minute>59)
minute=0;
hour++;
4.蜂鸣器与LED灯
#include "led.h"
#include "beep.h"
void LED_Init(void) //这些就没啥好说的了,最基础的LED、蜂鸣器初始化
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);//使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
void BEEP_Init(void)
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //BEEP-->PB.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据参数初始化GPIOB.8
GPIO_ResetBits(GPIOB,GPIO_Pin_8);//输出0,关闭蜂鸣器输出
5.主函数设计
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "timer.h"
#include "tpad.h"
#include "beep.h"
/*这里 u8 为 unsigned char;u16 为 unsigned int */
extern u8 hour, minute, second, t; //引入外部变量
extern u16 ms;
u8 h_set,m_set,s_set;//设置的时间,仅支持秒开始设置
u16 time_pause[4]=0,0,0,0,;//将四个时间变量存储在数组中,从而达到暂停的目的
void LCD_miaobiao()//显示
LCD_ShowxNum(30,162,hour,2,16,0x80); //显示数字
LCD_ShowString(47,162,200,2,16,":"); //显示字符串
LCD_ShowxNum(64,162,minute,2,16,0x80);
LCD_ShowString(81,162,200,2,16,":");
LCD_ShowxNum(97,162,second,2,16,0x80);
LCD_ShowString(114,162,200,2,16,":");
LCD_ShowxNum(140,162,ms,2,16,0x80);
void timeset()//闹钟的时间设置
LCD_ShowxNum(30,100,h_set,2,16,0x80);
LCD_ShowString(47,100,200,2,16,":");
LCD_ShowxNum(64,100,m_set,2,16,0x80);
LCD_ShowString(81,100,200,2,16,":");
LCD_ShowxNum(97,100,s_set,2,16,0x80);
int main(void)
u8 x=0; //触摸按键标志位
u8 key=0; //独立键盘标志位
u8 m=0; //LED闪烁标志位
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC
delay_init(); //延时函数初始化
BEEP_Init(); //蜂鸣器初始化
LED_Init(); //LED端口初始化
LCD_Init(); //LCD端口初始化
KEY_Init(); //独立按键初始化
TPAD_Init(6); //触摸按键初始化
LED_Init(); //LED初始化
TIM3_Int_Init(100,7199);//定时器初始化
while(1)
key=KEY_Scan(0);
x=TPAD_Scan();//触摸按键
if(key)
switch(key)
case WKUP_PRES:
hour=time_pause[0]; //将数组time_pause[]值赋给定时器中的时分秒,完成初始化
minute=time_pause[1];
second=time_pause[2];
ms=time_pause[3];
while(1)
LCD_miaobiao();
delay_ms(10); //消抖
t=KEY_Scan(0);
if((hour==h_set)&&(minute==m_set)&&(second==s_set)) /*闹钟功能*/
BEEP=1;
delay_ms(300);
BEEP=0;
delay_ms(300);
h_set=0; //原本设置的闹钟时间归零
m_set=0;
s_set=0;
timeset();
hour=0; //秒表归零
minute=0;
second=0;
ms=0;
LCD_miaobiao();
if(t)
switch(t)
case KEY1_PRES: //秒表归零
second = 0;
minute = 0;
hour = 0;
ms=0;
time_pause[0]=0;
time_pause[1]=0;
time_pause[2]=0;
time_pause[3]=0;
LCD_miaobiao();
break;
case KEY0_PRES: //暂停
time_pause[0]=hour; //设置一个数组,并将当前定时器的值(时、分、秒、毫秒)存入数组内
time_pause[1]=minute;
time_pause[2]=second;
time_pause[3]=ms;
LCD_ShowxNum(30,162,timeSFM[0],2,16,0x80);
LCD_ShowString(47,162,200,2,16,":");
LCD_ShowxNum(64,162,timeSFM[1],2,16,0x80);
LCD_ShowString(81,162,200,2,16,":");
LCD_ShowxNum(97,162,timeSFM[2],2,16,0x80);
LCD_ShowString(114,162,200,2,16,":");
LCD_ShowxNum(140,162,timeSFM[3],2,16,0x80);
if(t==KEY0_PRES)
m=1;
if(m)
m=1;
LED1=0;
delay_ms(100);
LED1=1;
delay_ms(100);
else m=0;
break;
break ;
break;
else delay_ms(10);
if(x) //触摸按键实现设置闹钟功能
s_set++;
if(s_set>59)
s_set=0;
m_set++;
if(m_set>59)
m_set=0;
h_set++;
if以上是关于基于正点原子STM32F1精英版秒表(库函数版)的主要内容,如果未能解决你的问题,请参考以下文章
正点原子 精英版( 实验22 IIC实验 )Usmart 无效 出现不了函数清单