基于STM32单片机1602显示电子时钟

发布者:Serendipitous33最新更新时间:2022-12-07 来源: zhihu关键字:STM32  单片机  1602显示  电子时钟 手机看文章 扫描二维码
随时随地手机看文章

1、本系统采用1602显示时分秒,4个按键可以调整时间,一个按键是选择按键,一个按键是加,一个按键是减,一个按键是退出按键。


2、当选择按键按下的时候,该选择位闪烁。

主函数代码:

#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;

/*******************主函数************************/

int main(void)

{

//u8 t;

delay_init();//延时函数初始化

LCD1602_Init();//LCD1602初始化函数

TIM3_Int_Init(999,71);//1MS

TIM4_Int_Init(999,71);//1MS

KEY_Init(); //按键初始化

#IF0 //注释掉程序

LCD_Write_Command(0x80);//第一行的首地址

for(i=0;i<16;i++)

{

LCD_Write_Date(table1);

delay_ms(3);

}

LCD_Write_Command(0xc0);//第二行的首地址

for(i=0;i<16;i++)

{

LCD_Write_Date(table2);

delay_ms(3);

}

#endif

while(1)

{


display(shi,fen,miao);

keyscan();

}



}

定时器代码

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通道被使能

NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器

TIM_Cmd(TIM3, ENABLE); //使能TIMx

}

//3中断服务程序

void TIM3_IRQHandler(void) //TIM3中断

{

static u16 count=0;

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否

{

TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志

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;

}

}

}


}

}

//通用定时器4中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

void TIM4_Int_Init(u16 arr,u16 psc)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能


//定时器TIM4初始化

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(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位


TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断

//中断优先级NVIC设置

NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; //从优先级3级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器

TIM_Cmd(TIM4, ENABLE); //使能TIMx

}

//定时器4中断服务程序

void TIM4_IRQHandler(void) //TIM3中断

{

if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否

{

TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx更新中断标志

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端口时钟

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);//根据设定参数初始化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跟数据线 //LED1-->PE.5 端口配置, 推挽输出

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz

GPIO_Init(GPIOA, &GPIO_InitStructure);//根据设定参数初始化GPIOE

LCD_Write_Command(0x01);//清除屏幕显示

delay_ms(2);


LCD_Write_Command(0x38);//设置LCD两行显示,一个数据由5*7点阵表示,数据由8跟线传输

delay_ms(2);


LCD_Write_Command(0x06);//设定输入方式,增量不移位

delay_ms(2);

LCD_Write_Command(0x0c);//开整体显示,关光标,不闪烁

delay_ms(2);

}

/*******************写指令函数************************/

void LCD_Write_Command(u8 com)

{

GPIO_Write(GPIOA, 0X00FF&com);//该函数一般用来往一次性一个GPIO的多个端口设置

rs=0; //写指令函数和写数据函数其实可以并一起价格 BOOL变量判断是写指令就rs=0写数据就rs=1。

rw=0;

en=0; //写指令 输入:RS=L,RW=L,E=下降沿脉冲

delay_ms(2);

en=1;

delay_ms(2);

en=0;

}

/*******************写数据函数************************/

void LCD_Write_Date(u8 date)

{

GPIO_Write(GPIOA,0X00FF&date);//GPIOA的第八位用来作为8位数据口

rs=1;

rw=0;

en=0; //写指令 输入:RS=L,RW=L,E=下降沿脉冲

delay_ms(2);

en=1;

delay_ms(2);

en=0;

}

/******************************************************************************

函数名称:LCD1602_MoveToPosition

函数功能:将液晶的光标移动到指定的位置

入口参数:x-液晶显示的行数,范围0-1

x = 0:在液晶的第一行

x = 1:在液晶的第二行

y-液晶显示的列数,范围0-15

y = 0:在液晶的第一列

y = 1:在液晶的第二列

......

y = 15:在液晶的第十六列

返回值:无

备注:通过指定x,y的值可以将液晶的光标移动到指定的位置

*******************************************************************************/

void LCD1602_MoveToPosition(u8 x,u8 y)

{

if(0 == x)

LCD_Write_Command(0x80 | y); //光标定位到第一行的y列

if(1 == x)

LCD_Write_Command(0xC0 | y); //光标定义到第二行的y列

}

/******************************************************************************

函数名称:LCD1602_DisplayOneCharOnAddr

函数功能:在指定的位置上显示指定的字符

入口参数:x-液晶显示的行数,范围0-1

x = 0:在液晶的第一行

x = 1:在液晶的第二行

y-液晶显示的列数,范围0-15

y = 0:在液晶的第一列

y = 1:在液晶的第二列

......

y = 15:在液晶的第十六列

ucData-要显示的字符数据

返回值:无

备注:确保x,y的取值要在指定的范围内

*******************************************************************************/

void LCD1602_DisplayOneCharOnAddr(u8 x,u8 y,u8 ucData)

{

LCD1602_MoveToPosition(x,y); //光标位置

LCD_Write_Date(ucData); //写入数据

}

/******************************************************************************

函数名称:LCD1602_DisplayString

函数功能:显示字符串

入口参数:ucStr-字符串的首地址

返回值:无

备注:无

*******************************************************************************/

void LCD1602_DisplayString(u8 *ucStr)

{

while(*ucStr != '') //字符串结束之前,循环显示

{

LCD_Write_Date(*ucStr); //依次写入每一个字符

ucStr++; //指针增加

}

}

/*****************控制光标函数********************/

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); //显示光标并且闪烁

else

LCD_Write_Command(0x0c); //关闭光标

}

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);

}

}

}


关键字:STM32  单片机  1602显示  电子时钟 引用地址:基于STM32单片机1602显示电子时钟

上一篇:STM32单片机外部中断配置讲解
下一篇:关于STM32库函数的代码性能对比

推荐阅读最新更新时间:2024-10-28 13:44

PIC单片机之IO口映射问题
我们可以在手册上看到管脚分布表: 和管脚映射有关的是:RP0~RP31(双向映射,既能够做输出映射也能够作为输入映射),共32个管脚 RPI32~RPI43(只能够作为输入映射,不能够作为输出映射),共12个管脚 拥有映射功能的一共是44个管脚 对于输入方向的映射方法是这样的: RPINR0~RPINR27这些寄存器中的 和 都对应着某个功能要映射到的RPINR 管脚,比如RPINR0 就对应着INT1(外部中断1)要映射到的管脚数,如果RPINR0 =0,那么RP0就映射给了中断1,也就是说功能是定死的,但是这个功能要映射到哪个管脚是可以配置的 输出映射的方法和输入映射的方法恰恰相反,对于输出来说,管脚是定
[单片机]
PIC<font color='red'>单片机</font>之IO口映射问题
基于STCl2C5A60S2单片机的SD卡读写
O 引言 SD卡是一种微型、低功耗、可移动的Flash多功能存储卡,该卡向上兼容MMC卡,并增加了智能保护机制,以有效地防止盗版,同时具有更快的传输速率及更高的存储容量,可广泛用于便携式消费类电子产品中。本文首先介绍了STC12C5A60S2单片机在SPI协议下与SD卡的硬件接口电路,然后简要阐述了SPI总线模式以及软件模拟的SPI总线数据通讯,最后给出了实现SD卡的初始化和读写操作的软件流程。 1 STC单片机 STCl2C5A60S2/AD/PWM系列单片机是宏晶科技生产的单时钟/机器周期(IT)的单片机,这是一种高速、低功耗、超强抗干扰的新一代805l单片机,它的指令代码完全兼容传统8051,但速度比8051快8~
[单片机]
基于STCl2C5A60S2<font color='red'>单片机</font>的SD卡读写
基于AT89C52单片机的超低频信号发生器设计
低频以及超低频信号在医学、电化学研究和实验教学中都有广泛的应用,尤其在电化学领域里,超低频信号发生器已成为电化学仪器必不可少的组成部分。电化学仪器配以方波、三角波和正弦波发生器,可以研究电化学系统各种暂态行为;配以慢的线性扫描信号或阶梯波信号,可以自动进行稳态(或接近稳态)极化曲线测量。然而市面上适用于电化学领域的信号发生器很少,传统信号发生器无法满足专业需求,且购买成本太高。现介绍一种用单片机控制的信号发生器,可输出方波、三角波及正弦波。产生的波形信号频率范围是0.125 mHz(毫赫兹)~80 Hz,输出的模拟信号电压范围是-10~+10 V,输出信号的幅值和频率具有一定的调节范围。该信号发生器与传统的信号发生器相比,有如下的
[单片机]
基于AT89C52<font color='red'>单片机</font>的超低频信号发生器设计
单片机RAM的用法
任何一本单片机的数据都不会不提存储器的问题,但是没有基本能说的让人一下就领悟过来。菜鸟时候的特权也是一知半解的过来的,我想如果读51的存储器(主要是RAM)做一下归纳,列一张表,我想一定会让初学者少走很多弯路,希望这张表还有下面的一些个人的经验只谈能给你一些启迪。也许有些地方说的不是很专业,或者说是表达不太合适,很欢迎各路高手拍砖指正。EDN这个大家庭就是让我们互相学习共同进步的乐土! 51单片机存储区分配如下: 存储区 地址范围 功能说明 内部RAM (256Byte) 00H-1FH 内部使用DATA区,
[单片机]
TI推出单价不足2美元的新型32位MCU
日前,德州仪器( TI )宣布推出最低批量单价不足2 美元的新型32 位TMS320F280xx 微控制器 ( MCU ),从而可为成本敏感型应用实现处理器密集型的实时控制功能,并壮大了其 MCU 产品的整体阵营。新型 Piccolo F2802x/F2803x MCU 采用最新的架构技术成果及增强型外设,其封装尺寸最少为 38 引脚,能够为通常难以承担相应成本的应用带来 32 位实时控制功能的优势。实时控制通过在诸如太阳能微型逆变器、 LED 照明 、大型家用电器以及混合动力车载电池等工业、消费类及车载应用中实施高级算法,从而可实现更高的系统效率与精度。    TI 的 TMS320C2000 市场营销经理 Ke
[单片机]
流水灯的单片机控制设计
1.引言 当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化智能控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未见的速度被单片机智能控制系统所取代。单片机具有体积小、功能强、成本低、应用面广等优点,可以说,智能控制与自动控制的核心就是单片机。目前,一个学习与应用单片机的高潮正在工厂、学校及企事业单位大规模地兴起。学习单片机的最有效方法就是理论与实践并重,本文笔者用AT89C51单片机自制了一款简易的流水灯,重点介绍了其软件编程方法,以期给单片机初学者以启发,更快地成为单片机领域的优秀人才。 2.硬件组成 按照单片机系统扩展与系统配置状况,单片机应用系统可分为最小系统、最小功耗系统及典型系统等。A
[单片机]
流水灯的<font color='red'>单片机</font>控制设计
STM32 UART/USART 的差别
stm32中 uart 是比较常用的, 在使用 HAL时发现了 uart / usart, 原来用一直都没有太注意, 现在有闲时整理一下. 1、UART:universal asynchronous receiver and transmitter通用异步收发器, 仅需要 RX / TX 接口. 2、USART:universal synchronous asynchronous receiver and transmitter通用同步异步收发器, 除了 TX/RX 之外, 还额外需要一个 CLK 的 PIN 脚. 也就是说:UART的一般只能用于异步串行通讯,而名称为USART的既可以用于同步串行通讯,也能用于异步串行通讯。 在
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved