这文章来自互联网如有侵权请和管理员联系删除
项目描述:
用单片机实现0 ~ 99s的计时,将计时实时显示在LCD上,并用24C02实现掉电记忆。
仿真原理图如下:
C语言代码如下:/*------------------------
FileName: clock.h
Function: 头文件
Author: Zhang Kaizhou
Date: 2019-6-12 18:07:29
------------------------*/
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
/*IIC总线端口定义*/
sbit SDA = P2^0;
sbit SCL = P2^1;
/*LCD1602显示模块端口定义*/
sbit lcdrs = P1^2;
sbit lcdrw = P1^3;
sbit lcden = P1^4;
/*主函数模块函数声明*/
void writeData24C02(uchar address, uchar dat);
void readData24C02(uchar address, uchar * dat);
void checkData(uchar * dat);
void timerInit();
/*IIC总线模块函数声明*/
void initIIC();
void startIIC();
void responseIIC();
void stopIIC();
void writeDataIIC(uchar dat);
void readDataIIC(uchar * dat);
/*LCD1602显示模块函数声明*/
void LCDInit();
void display(uchar dat1, uchar dat2);
void writeCommand(uchar command);
void writeDataLCD(uchar dat);
void delay(uchar xms);/*--------------------------------------------
FileName: main.c
Function: 用单片机实现0 ~ 99s的计时,
将计时实时显示在LCD上,并用24C02实现掉电记忆;
Author: Zhang Kaizhou
Date: 2019-6-12 18:06:18
--------------------------------------------*/
#include "clock.h"
/*定义全局变量*/
uchar second = 0, count = 0;
bit flag = 0;
void main(){
LCDInit();
initIIC();
readData24C02(1, &second); // 通过IIC总线将24C02的第1个存储单元中的数据读取到变量second中
checkData(&second); // 首次读取数据时,原来芯片中的数据可能超过100(非法数据)
timerInit();
TR0 = 1; // 开始计时
while(1){
display(second / 10, second % 10);
if(flag){
flag = 0;
writeData24C02(1, second);
}
}
}
/*向24C02的任意地址address处写入数据dat*/
void writeData24C02(uchar address, uchar dat){
startIIC();
writeDataIIC(0xa0); // 向IIC总线发送寻址信号,并声明要进行写操作
responseIIC();
writeDataIIC(address);
responseIIC();
writeDataIIC(dat);
responseIIC();
stopIIC();
}
/*从24C02的任意地址address处读出数据到变量dat*/
void readData24C02(uchar address, uchar * dat){
startIIC();
writeDataIIC(0xa0);
responseIIC();
writeDataIIC(address);
responseIIC();
startIIC();
writeDataIIC(0xa1); // 向IIC总线发送寻址信号,并声明要进行读操作
responseIIC();
readDataIIC(dat);
stopIIC();
}
/*检测从24C02读取的数据是否合法*/
void checkData(uchar * dat){
if((* dat) > 100){
* dat = 0;
}
}
/*timer初始化*/
void timerInit(){
TMOD = 0x01; // timer0 定时模式 工作方式1(16位定时器)
TH0 = (65536 - 46080) / 256; // 系统晶振为11.0592MHz,定时50ms
TL0 = (65536 - 46080) % 256;
ET0 = 1; // 开定时器0溢出中断
EA = 1; // 开全局中断
}
/*timer0溢出中断服务程序*/
void timer0Service() interrupt 1{
TH0 = (65536 - 46080) / 256; // 重装初值
TL0 = (65536 - 46080) % 256;
count++;
if(count == 20){ // 50ms * 20 = 1s
count = 0;
second++;
flag = 1;
if(second == 100){ // 0 ~ 99s
second = 0;
}
}
}/*------------------------------
FileName: IIC.c
Function: 实现IIC总线的基本操作
Author: Zhang Kaizhou
Date: 2019-6-12 18:08:47
------------------------------*/
#include "clock.h"
/*IIC总线初始化*/
void initIIC(){
SCL = 1;
_nop_();
SDA = 1;
_nop_();
}
/*IIC总线启动信号*/
void startIIC(){ // 在SCL高电平期间,SDA产生一个下降沿表示启动
SDA = 1;
_nop_();
SCL = 1;
_nop_();
SDA = 0;
_nop_();
}
/*IIC总线应答信号*/
void responseIIC(){ // 从机在SCL高电平期间将SDA拉低表示应答
SDA = 0;
_nop_();
SCL = 1;
_nop_();
SCL = 0;
_nop_();
}
/*IIC总线停止信号*/
void stopIIC(){ // 在SCL高电平期间,SDA产生一个上升沿表示停止
SDA = 0;
_nop_();
SCL = 1;
_nop_();
SDA = 1;
_nop_();
}
/*向IIC总线写一个字节数据*/
void writeDataIIC(uchar dat){
uchar i, temp;
temp = dat;
for(i = 0; i < 8; i++){
temp = temp << 1;
SCL = 0;
_nop_();
SDA = CY;
_nop_();
SCL = 1;
_nop_();
}
SCL = 0;
_nop_();
SDA = 1;
_nop_();
}
/*从IIC总线读一个字节数据*/
void readDataIIC(uchar * dat){
uchar i;
SCL = 0;
_nop_();
SDA = 1;
_nop_();
for(i = 0; i < 8; i++){
SCL = 1;
_nop_();
* dat = ((* dat) << 1) | SDA;
SCL = 0;
_nop_();
}
}/*-----------------------------
FileName:display.c
Function: LCD1602显示函数
Author: Zhang Kaizhou
Date: 2019-6-12 18:09:16
------------------------------*/
#include "clock.h"
uchar code table0[] = {"Timekeeping"};
uchar code table1[] = {"Time:"};
uchar code table2[] = {"0123456789"};
uchar num = 0;
/*初始化LCD1602的设置*/
void LCDInit(){
uchar i;
lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
writeCommand(0x0c); // 开显示,不显示光标
writeCommand(0x06); // 写一个字符后地址指针自动加1
writeCommand(0x01); // 显示清零,数据指针清零
/*LCD上电界面*/
writeCommand(0x80); // 将数据指针定位到第一行首
for(i = 0; i < strlen(table0); i++){
writeDataLCD(table0[i]);
delay(5);
}
writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
for(i = 0; i < strlen(table1); i++){
writeDataLCD(table1[i]);
delay(5);
}
}
/*LCD显示函数*/
void display(uchar dat1, uchar dat2){
writeCommand(0x80 + 0x40 + strlen(table1));
writeDataLCD(table2[dat1]);
delay(5);
writeCommand(0x80 + 0x40 + strlen(table1) + 1);
writeDataLCD(table2[dat2]);
delay(5);
}
/*写指令函数*/
void writeCommand(uchar command){
lcdrs = 0; // 命令选择
lcdrw = 0;
P0 = command;
delay(5);
lcden = 1; // 产生一个正脉冲使能信号
delay(5);
lcden = 0;
}
/*写数据函数*/
void writeDataLCD(uchar dat){
lcdrs = 1; // 数据选择
lcdrw = 0;
P0 = dat;
delay(5);
lcden = 1;
delay(5);
lcden = 0;
}
/*延时xms函数*/
void delay(uchar xms){
uchar i, j;
for(i = xms; i > 0; i--)
for(j = 110; j > 0; j--);
}