標(biāo)題:
基于STM32單片機(jī)電子時(shí)鐘程序,1602顯示,時(shí)間可調(diào)
[打印本頁(yè)]
作者:
bbxyliyang
時(shí)間:
2019-10-14 19:27
標(biāo)題:
基于STM32單片機(jī)電子時(shí)鐘程序,1602顯示,時(shí)間可調(diào)
1、本系統(tǒng)采用1602顯示時(shí)分秒,4個(gè)按鍵可以調(diào)整時(shí)間,一個(gè)按鍵是選擇按鍵,一個(gè)按鍵是加,一個(gè)按鍵是減,一個(gè)按鍵是退出按鍵。
2、當(dāng)選擇按鍵按下的時(shí)候,該選擇位閃爍。
主函數(shù)代碼:
#include "delay.h"
#include "sys.h"
#include "1602.h"
#include "timer.h"
#include "key.h"
u8 table1[]="liyang " ;
u8 table2[]="9876543210654321" ;
signed char miao,fen,shi;
u8 flag_100ms=0;
u16 count_ms=0;
u8 S1num;
/*******************主函數(shù)************************/
int main(void)
{
//u8 t;
delay_init();//延時(shí)函數(shù)初始化
LCD1602_Init();//LCD1602初始化函數(shù)
TIM3_Int_Init(999,71);//1MS
TIM4_Int_Init(999,71);//1MS
KEY_Init(); //按鍵初始化
#[color=#0066cc]IF[/color] 0 //注釋掉程序
LCD_Write_Command(0x80);//第一行的首地址
for(i=0;i<16;i++)
{
LCD_Write_Date(table1[i]);
delay_ms(3);
}
LCD_Write_Command(0xc0);//第二行的首地址
for(i=0;i<16;i++)
{
LCD_Write_Date(table2[i]);
delay_ms(3);
}
#endif
while(1)
{
display(shi,fen,miao);
keyscan();
}
}
定時(shí)器代碼
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //[color=#0066cc]時(shí)鐘[/color]使能
//定時(shí)器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷
//中斷優(yōu)先級(jí)NVIC設(shè)置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級(jí)3級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//3中斷服務(wù)程序
void TIM3_IRQHandler(void) //TIM3中斷
{
static u16 count=0;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查T(mén)IM3更新中斷發(fā)生與否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中斷標(biāo)志
count++;
count_ms++;
if(count_ms==500)
{
count_ms=0;
flag_100ms=~flag_100ms;
}
if(count==1000)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
shi=0;
}
}
}
}
}
//通用定時(shí)器4中斷初始化
//這里時(shí)鐘選擇為APB1的2倍,而APB1為36M
//arr:自動(dòng)重裝值。
//psc:時(shí)鐘預(yù)分頻數(shù)
//這里使用的是定時(shí)器3!
void TIM4_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //時(shí)鐘使能
//定時(shí)器TIM4初始化
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中斷,允許更新中斷
//中斷優(yōu)先級(jí)NVIC設(shè)置
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; //從優(yōu)先級(jí)3級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM4, ENABLE); //使能TIMx
}
//定時(shí)器4中斷服務(wù)程序
void TIM4_IRQHandler(void) //TIM3中斷
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //檢查T(mén)IM3更新中斷發(fā)生與否
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx更新中斷標(biāo)志
count_ms++;
if(count_ms==500)
{
count_ms=0;
flag_100ms=~flag_100ms;
}
}
}
1602代碼
#include"1602.h"
#include"sys.h"
#include "delay.h"
extern u8 S1num;
extern u8 flag_100ms;
/*******************LCD1602初始化************************/
void LCD1602_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOA, ENABLE); //使能PA,PC端口時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; //LCD1602的三根控制線rs,rw,en
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度為50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_Init(GPIOE, &GPIO_InitStructure);//根據(jù)設(shè)定參數(shù)初始化GPIOE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//LCD1602的8跟數(shù)據(jù)線 //[color=#0066cc]LED[/color]1-->PE.5 端口配置, 推挽輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);//根據(jù)設(shè)定參數(shù)初始化GPIOE
LCD_Write_Command(0x01);//清除屏幕顯示
delay_ms(2);
LCD_Write_Command(0x38);//設(shè)置LCD兩行顯示,一個(gè)數(shù)據(jù)由5*7點(diǎn)陣表示,數(shù)據(jù)由8跟線傳輸
delay_ms(2);
LCD_Write_Command(0x06);//設(shè)定輸入方式,增量不移位
delay_ms(2);
LCD_Write_Command(0x0c);//開(kāi)整體顯示,關(guān)光標(biāo),不閃爍
delay_ms(2);
}
/*******************寫(xiě)指令函數(shù)************************/
void LCD_Write_Command(u8 com)
{
GPIO_Write(GPIOA, 0X00FF&com);//該函數(shù)一般用來(lái)往一次性一個(gè)GPIO的多個(gè)端口設(shè)置
rs=0; //寫(xiě)指令函數(shù)和寫(xiě)數(shù)據(jù)函數(shù)其實(shí)可以并一起價(jià)格 BOOL變量判斷是寫(xiě)指令就rs=0寫(xiě)數(shù)據(jù)就rs=1。
rw=0;
en=0; //寫(xiě)指令 輸入:RS=L,RW=L,E=下降沿脈沖
delay_ms(2);
en=1;
delay_ms(2);
en=0;
}
/*******************寫(xiě)數(shù)據(jù)函數(shù)************************/
void LCD_Write_Date(u8 date)
{
GPIO_Write(GPIOA,0X00FF&date);//GPIOA的第八位用來(lái)作為8位數(shù)據(jù)口
rs=1;
rw=0;
en=0; //寫(xiě)指令 輸入:RS=L,RW=L,E=下降沿脈沖
delay_ms(2);
en=1;
delay_ms(2);
en=0;
}
/******************************************************************************
函數(shù)名稱:LCD1602_MoveToPosition
函數(shù)功能:將液晶的光標(biāo)移動(dòng)到指定的位置
入口參數(shù):x-液晶顯示的行數(shù),范圍0-1
x = 0:在液晶的第一行
x = 1:在液晶的第二行
y-液晶顯示的列數(shù),范圍0-15
y = 0:在液晶的第一列
y = 1:在液晶的第二列
......
y = 15:在液晶的第十六列
返回值:無(wú)
備注:通過(guò)指定x,y的值可以將液晶的光標(biāo)移動(dòng)到指定的位置
*******************************************************************************/
void LCD1602_MoveToPosition(u8 x,u8 y)
{
if(0 == x)
LCD_Write_Command(0x80 | y); //光標(biāo)定位到第一行的y列
if(1 == x)
LCD_Write_Command(0xC0 | y); //光標(biāo)定義到第二行的y列
}
/******************************************************************************
函數(shù)名稱:LCD1602_DisplayOneCharOnAddr
函數(shù)功能:在指定的位置上顯示指定的字符
入口參數(shù):x-液晶顯示的行數(shù),范圍0-1
x = 0:在液晶的第一行
x = 1:在液晶的第二行
y-液晶顯示的列數(shù),范圍0-15
y = 0:在液晶的第一列
y = 1:在液晶的第二列
......
y = 15:在液晶的第十六列
ucData-要顯示的字符數(shù)據(jù)
返回值:無(wú)
備注:確保x,y的取值要在指定的范圍內(nèi)
*******************************************************************************/
void LCD1602_DisplayOneCharOnAddr(u8 x,u8 y,u8 ucData)
{
LCD1602_MoveToPosition(x,y); //光標(biāo)位置
LCD_Write_Date(ucData); //寫(xiě)入數(shù)據(jù)
}
/******************************************************************************
函數(shù)名稱:LCD1602_DisplayString
函數(shù)功能:顯示字符串
入口參數(shù):ucStr-字符串的首地址
返回值:無(wú)
備注:無(wú)
*******************************************************************************/
void LCD1602_DisplayString(u8 *ucStr)
{
while(*ucStr != '\0') //字符串結(jié)束之前,循環(huán)顯示
{
LCD_Write_Date(*ucStr); //依次寫(xiě)入每一個(gè)字符
ucStr++; //指針增加
}
}
/*****************控制光標(biāo)函數(shù)********************/
void write_guanbiao(u8 hang,u8 add,u8 date)
{
if(hang==1)
LCD_Write_Command(0x80+add);
else
LCD_Write_Command(0x80+0x40+add);
if(date == 1)
LCD_Write_Command(0x0f); //顯示光標(biāo)并且閃爍
else
LCD_Write_Command(0x0c); //關(guān)閉光標(biāo)
}
void display(u8 aa,u8 bb,u8 cc)
{
if(S1num!=3)
{
LCD1602_DisplayOneCharOnAddr(1,0,aa/10+0x30);
LCD1602_DisplayOneCharOnAddr(1,1,aa%10+0x30);
}
else
{
if(flag_100ms==0)
{
LCD1602_DisplayOneCharOnAddr(1,0,' ');
LCD1602_DisplayOneCharOnAddr(1,1,' ');
}
else
{
LCD1602_DisplayOneCharOnAddr(1,0,aa/10+0x30);
LCD1602_DisplayOneCharOnAddr(1,1,aa%10+0x30);
}
}
LCD1602_DisplayOneCharOnAddr(1,2,':');
if(S1num!=2)
{
LCD1602_DisplayOneCharOnAddr(1,3,bb/10+0x30);
LCD1602_DisplayOneCharOnAddr(1,4,bb%10+0x30);
}
else
{
if(flag_100ms==0)
{
LCD1602_DisplayOneCharOnAddr(1,3,' ');
LCD1602_DisplayOneCharOnAddr(1,4,' ');
}
else
{
LCD1602_DisplayOneCharOnAddr(1,3,bb/10+0x30);
LCD1602_DisplayOneCharOnAddr(1,4,bb%10+0x30);
}
}
LCD1602_DisplayOneCharOnAddr(1,5,':');
if(S1num!=1)
{
LCD1602_DisplayOneCharOnAddr(1,6,cc/10+0x30);
LCD1602_DisplayOneCharOnAddr(1,7,cc%10+0x30);
}
else
{
if(flag_100ms==0)
{
LCD1602_DisplayOneCharOnAddr(1,6,' ');
LCD1602_DisplayOneCharOnAddr(1,7,' ');
}
else
{
LCD1602_DisplayOneCharOnAddr(1,6,cc/10+0x30);
LCD1602_DisplayOneCharOnAddr(1,7,cc%10+0x30);
}
}
}
復(fù)制代碼
作者:
bbxyliyang
時(shí)間:
2020-2-27 14:09
庫(kù)函數(shù)開(kāi)發(fā)的小結(jié):
我們一般使用ST庫(kù)對(duì)外設(shè)進(jìn)行初始化,一般有以下布驟:
1)定義一個(gè)XXX_InitTypeDef類型的初始化結(jié)構(gòu)體。
2)根據(jù)自己的需求,向這些初始化結(jié)構(gòu)體的成員寫(xiě)入特定的控制參數(shù)。
3)填充好結(jié)構(gòu)體之后,把這個(gè)結(jié)構(gòu)體作為輸入?yún)?shù)調(diào)用相應(yīng)的外設(shè)庫(kù)函數(shù)XXX _Init();從而實(shí)現(xiàn)向寄存器寫(xiě)入控制參數(shù),并配置好外設(shè)。
作者:
R.是桃子啊
時(shí)間:
2020-5-15 11:45
樓主 請(qǐng)問(wèn)有電路圖嗎?
作者:
kidxpp
時(shí)間:
2021-3-13 10:43
有工程文件嗎 UP主
作者:
bbxyliyang
時(shí)間:
2022-7-31 20:13
kidxpp 發(fā)表于 2021-3-13 10:43
有工程文件嗎 UP主
有的
作者:
早起橘
時(shí)間:
2023-12-2 20:20
可以發(fā)一下工程文件嗎樓主
作者:
阿哩吖咔通
時(shí)間:
2024-5-13 15:31
能分享一下文件嗎樓主
作者:
lq1619
時(shí)間:
2024-5-17 23:43
謝謝樓主分享的資料
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1