基于正點原子STM32F1精英版秒表(庫函式版)
- 一、前期準備
- 二、代碼實作:
- 1.獨立按鍵與觸摸按鍵
- 2.TFTLCD
- 3.定時器
- 4.蜂鳴器與LED燈
- 5.主函式設計
- 三、 結束語:
一、前期準備
- 建立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(h_set>24)
{
h_set=0;
}
}
}
timeset();
delay_ms(10);
}
}
}
三、 結束語:
筆者編輯完這篇文章的時候,板子不在身邊,無法運行出實際效果來展示,但已經將該程式的壓縮包打包上傳了,想進一步了解的話可以下載來看看,
筆者剛入坑小白一枚,文中謬誤,還請不吝賜教,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280557.html
標籤:其他
