1. arino驅動的ds3231時鍾模塊的代碼編譯通不過
最近這個模塊我用過,感覺挺好的,用的是I2C方式通訊的。初步看了下你用的代碼,風格不好。建議使用最新的庫文件,主程序也很簡單。
庫文件下載:https://github.com/jcastaneyra/ds3231_library
你看下庫中自帶的example,應該能馬上看懂的。不知你用的是arino uno嗎?arino IDE是不是1.0.5?建議使用1.0.5版本,兼容性較好。如還有其他疑問,我們可以交流下。
2. 51單片機時鍾程序,C語言,匯編都行
我給你個,你試試把。
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include <intrins.h>
sbit SCK=P3^; //時鍾
sbit SDA=P3^4; //數據
sbit RST = P3^5;// DS1302復位
sbit LS138A=P2^2;
sbit LS138B=P2^3;
sbit LS138C=P2^4;
bit ReadRTC_Flag;//定義讀DS1302標志
unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分時日月周年08-05-15 12:00:00
unsigned char l_tmpdisplay[8];
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分時日月周年 最低位讀寫位
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
//共陰數碼管 0-9 '-' '熄滅『表
/******************************************************************/
/* 函數聲明 */
/******************************************************************/
void Write_Ds1302_byte(unsigned char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_RTC(void);//read RTC
void Set_RTC(void); //set RTC
void InitTIMER0(void);//inital timer0
/******************************************************************/
/* 主函數 */
/******************************************************************/
void main(void)
{
InitTIMER0(); //初始化定時器0
Set_RTC(); //寫入時鍾值,如果使用備用電池時候,不需要沒每次上電寫入,此程序應該屏蔽
while(1)
{
if(ReadRTC_Flag)
{
ReadRTC_Flag=0;
Read_RTC();
l_tmpdisplay[0]=l_tmpdate[2]/16; //數據的轉換,因我們採用數碼管0~9的顯示,將數據分開
l_tmpdisplay[1]=l_tmpdate[2]&0x0f;
l_tmpdisplay[2]=10; //加入"-"
l_tmpdisplay[3]=l_tmpdate[1]/16;
l_tmpdisplay[4]=l_tmpdate[1]&0x0f;
l_tmpdisplay[5]=10;
l_tmpdisplay[6]=l_tmpdate[0]/16;
l_tmpdisplay[7]=l_tmpdate[0]&0x0f;
}
}
}
/******************************************************************/
/* 定時器0初始化 */
/******************************************************************/
void InitTIMER0(void)
{
TMOD|=0x01;//定時器設置 16位
TH0=0xef;//初始化值
TL0=0xf0;
ET0=1;
TR0=1;
EA=1;
}
/******************************************************************/
/* 寫一個位元組 */
/******************************************************************/
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++) //循環8次 寫入數據
{
SCK=0;
SDA=temp&0x01; //每次傳輸低位元組
temp>>=1; //右移一位
SCK=1;
}
}
/******************************************************************/
/* 寫入DS1302 */
/******************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_(); //啟動
Write_Ds1302_Byte(address); //發送地址
Write_Ds1302_Byte(dat); //發送數據
RST=0; //恢復
}
/******************************************************************/
/* 讀出DS1302數據 */
/******************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循環8次 讀取數據
{
if(SDA)
temp|=0x80; //每次傳輸低位元組
SCK=0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_(); //以下為DS1302復位的穩定時間
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
return (temp); //返回
}
/******************************************************************/
/* 讀時鍾數據 */
/******************************************************************/
void Read_RTC(void) //讀取 日歷
{
unsigned char i,*p;
p=read_rtc_address; //地址傳遞
for(i=0;i<7;i++) //分7次讀取 秒分時日月周年
{
l_tmpdate[i]=Read_Ds1302(*p);
p++;
}
}
/******************************************************************/
/* 設定時鍾數據 */
/******************************************************************/
void Set_RTC(void) //設定 日歷
{
unsigned char i,*p,tmp;
for(i=0;i<7;i++){ //BCD處理
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp*16;
}
Write_Ds1302(0x8E,0X00);
p=write_rtc_address; //傳地址
for(i=0;i<7;i++) //7次寫入 秒分時日月周年
{
Write_Ds1302(*p,l_tmpdate[i]);
p++;
}
Write_Ds1302(0x8E,0x80);
}
/******************************************************************/
/* 定時器中斷函數 */
/******************************************************************/
void tim(void) interrupt 1 using 1
//中斷,用於數碼管掃描
{
static unsigned char i,num;
TH0=0xf5;
TL0=0xe0;
P0=table[l_tmpdisplay[i]]; //查表法得到要顯示數字的數碼段
switch(i)
{
case 0:LS138A=0; LS138B=0; LS138C=0; break;
case 1:LS138A=1; LS138B=0; LS138C=0; break;
case 2:LS138A=0; LS138B=1; LS138C=0; break;
case 3:LS138A=1; LS138B=1; LS138C=0; break;
case 4:LS138A=0; LS138B=0; LS138C=1; break;
case 5:LS138A=1; LS138B=0; LS138C=1; break;
case 6:LS138A=0; LS138B=1; LS138C=1; break;
case 7:LS138A=1; LS138B=1; LS138C=1; break;
}
i++;
if(i==8)
{
i=0;
num++;
if(10==num) //隔段時間讀取1302的數據。時間間隔可以調整
{
ReadRTC_Flag=1; //使用標志位判斷
num=0;
}
}
}
3. 單片機做時鍾程序
基於DS1302的日歷時鍾
#include<reg51.h> //包含單片機寄存器的頭文件
#include<intrins.h> //包含_nop_()函數定義的頭文件
/***********************************************************************
以下是DS1302晶元的操作程序
************************************************************************/
unsigned char code digit[10]={"0123456789"}; //定義字元數組顯示數字
sbit DATA=P1^1; //位定義1302晶元的介面,數據輸出端定義在P1.1引腳
sbit RST=P1^2; //位定義1302晶元的介面,復位埠定義在P1.1引腳
sbit SCLK=P1^0; //位定義1302晶元的介面,時鍾輸出埠定義在P1.1引腳
/*****************************************************
函數功能:延時若干微秒
入口參數:n
***************************************************/
void delaynus(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
;
}
/*****************************************************
函數功能:向1302寫一個位元組數據
入口參數:x
***************************************************/
void Write1302(unsigned char dat)
{
unsigned char i;
SCLK=0; //拉低SCLK,為脈沖上升沿寫入數據做好准備
delaynus(2); //稍微等待,使硬體做好准備
for(i=0;i<8;i++) //連續寫8個二進制位數據
{
DATA=dat&0x01; //取出dat的第0位數據寫入1302
delaynus(2); //稍微等待,使硬體做好准備
SCLK=1; //上升沿寫入數據
delaynus(2); //稍微等待,使硬體做好准備
SCLK=0; //重新拉低SCLK,形成脈沖
dat>>=1; //將dat的各數據位右移1位,准備寫入下一個數據位
}
}
/*****************************************************
函數功能:根據命令字,向1302寫一個位元組數據
入口參數:Cmd,儲存命令字;dat,儲存待寫的數據
***************************************************/
void WriteSet1302(unsigned char Cmd,unsigned char dat)
{
RST=0; //禁止數據傳遞
SCLK=0; //確保寫數居前SCLK被拉低
RST=1; //啟動數據傳輸
delaynus(2); //稍微等待,使硬體做好准備
Write1302(Cmd); //寫入命令字
Write1302(dat); //寫數據
SCLK=1; //將時鍾電平置於已知狀態
RST=0; //禁止數據傳遞
}
/*****************************************************
函數功能:從1302讀一個位元組數據
入口參數:x
***************************************************/
unsigned char Read1302(void)
{
unsigned char i,dat;
delaynus(2); //稍微等待,使硬體做好准備
for(i=0;i<8;i++) //連續讀8個二進制位數據
{
dat>>=1; //將dat的各數據位右移1位,因為先讀出的是位元組的最低位
if(DATA==1) //如果讀出的數據是1
dat|=0x80; //將1取出,寫在dat的最高位
SCLK=1; //將SCLK置於高電平,為下降沿讀出
delaynus(2); //稍微等待
SCLK=0; //拉低SCLK,形成脈沖下降沿
delaynus(2); //稍微等待
}
return dat; //將讀出的數據返回
}
/*****************************************************
函數功能:根據命令字,從1302讀取一個位元組數據
入口參數:Cmd
***************************************************/
unsigned char ReadSet1302(unsigned char Cmd)
{
unsigned char dat;
RST=0; //拉低RST
SCLK=0; //確保寫數居前SCLK被拉低
RST=1; //啟動數據傳輸
Write1302(Cmd); //寫入命令字
dat=Read1302(); //讀出數據
SCLK=1; //將時鍾電平置於已知狀態
RST=0; //禁止數據傳遞
return dat; //將讀出的數據返回
}
/*****************************************************
函數功能: 1302進行初始化設置
***************************************************/
void Init_DS1302(void)
{
WriteSet1302(0x8E,0x00); //根據寫狀態寄存器命令字,寫入不保護指令
WriteSet1302(0x80,((0/10)<<4|(0%10))); //根據寫秒寄存器命令字,寫入秒的初始值
WriteSet1302(0x82,((0/10)<<4|(0%10))); //根據寫分寄存器命令字,寫入分的初始值
WriteSet1302(0x84,((12/10)<<4|(12%10))); //根據寫小時寄存器命令字,寫入小時的初始值
WriteSet1302(0x86,((16/10)<<4|(16%10))); //根據寫日寄存器命令字,寫入日的初始值
WriteSet1302(0x88,((11/10)<<4|(11%10))); //根據寫月寄存器命令字,寫入月的初始值
WriteSet1302(0x8c,((8/10)<<4|(8%10))); //根據寫小時寄存器命令字,寫入小時的初始值
}
/*******************************************************************************
以下是對液晶模塊的操作程序
*******************************************************************************/
sbit RS=P2^0; //寄存器選擇位,將RS位定義為P2.0引腳
sbit RW=P2^1; //讀寫選擇位,將RW位定義為P2.1引腳
sbit E=P2^2; //使能信號位,將E位定義為P2.2引腳
sbit BF=P0^7; //忙碌標志位,,將BF位定義為P0.7引腳
/*****************************************************
函數功能:延時1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函數功能:延時若干毫秒
入口參數:n
***************************************************/
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
bit BusyTest(void)
{
bit result;
RS=0; //根據規定,RS為低電平,RW為高電平時,可以讀狀態
RW=1;
E=1; //E=1,才允許讀寫
_nop_(); //空操作
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
result=BF; //將忙碌標志電平賦給result
E=0; //將E恢復低電平
return result;
}
/*****************************************************
函數功能:將模式設置指令或顯示地址寫入液晶模塊
入口參數:dictate
***************************************************/
void WriteInstruction (unsigned char dictate)
{
while(BusyTest()==1); //如果忙就等待
RS=0; //根據規定,RS和R/W同時為低電平時,可以寫入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
_nop_();
_nop_(); //空操作兩個機器周期,給硬體反應時間
P0=dictate; //將數據送入P0口,即寫入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:指定字元顯示的實際地址
入口參數:x
***************************************************/
void WriteAddress(unsigned char x)
{
WriteInstruction(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"
}
/*****************************************************
函數功能:將數據(字元的標准ASCII碼)寫入液晶模塊
入口參數:y(為字元常量)
***************************************************/
void WriteData(unsigned char y)
{
while(BusyTest()==1);
RS=1; //RS為高電平,RW為低電平時,可以寫入數據
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
P0=y; //將數據送入P0口,即將數據寫入液晶模塊
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:對LCD的顯示模式進行初始化設置
***************************************************/
void LcdInitiate(void)
{
delaynms(15); //延時15ms,首次寫指令時應給LCD一段較長的反應時間
WriteInstruction(0x38); //顯示模式設置:16×2顯示,5×7點陣,8位數據介面
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x38);
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x38); //連續三次,確保初始化成功
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x0c); //顯示模式設置:顯示開,無游標,游標不閃爍
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x06); //顯示模式設置:游標右移,字元不移
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x01); //清屏幕指令,將以前的顯示內容清除
delaynms(5); //延時5ms,給硬體一點反應時間
}
/**************************************************************
以下是1302數據的顯示程序
**************************************************************/
/*****************************************************
函數功能:顯示秒
入口參數:x
***************************************************/
void DisplaySecond(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x49); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示分鍾
入口參數:x
***************************************************/
void DisplayMinute(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x46); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示小時
入口參數:x
***************************************************/
void DisplayHour(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x43); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示日
入口參數:x
***************************************************/
void DisplayDay(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x0c); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示月
入口參數:x
***************************************************/
void DisplayMonth(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x09); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示年
入口參數:x
***************************************************/
void DisplayYear(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x06); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:主函數
***************************************************/
void main(void)
{
unsigned char second,minute,hour,day,month,year; //分別儲存苗、分、小時,日,月,年
unsigned char ReadValue; //儲存從1302讀取的數據
LcdInitiate(); //將液晶初始化
WriteAddress(0x01); //寫Date的顯示地址,將在第1行第2列開始顯示
WriteData('D'); //將字元常量寫入LCD
WriteData('a'); //將字元常量寫入LCD
WriteData('t'); //將字元常量寫入LCD
WriteData('e'); //將字元常量寫入LCD
WriteData(':'); //將字元常量寫入LCD
WriteAddress(0x08); //寫年月分隔符的顯示地址, 顯示在第1行第9列
WriteData('-'); //將字元常量寫入LCD
WriteAddress(0x0b); //寫月日分隔符的顯示地址, 顯示在第1行第12列
WriteData('-'); //將字元常量寫入LCD
WriteAddress(0x45); //寫小時與分鍾分隔符的顯示地址, 顯示在第2行第6列
WriteData(':'); //將字元常量寫入LCD
WriteAddress(0x48); //寫分鍾與秒分隔符的顯示地址, 顯示在第2行第9列
WriteData(':'); //將字元常量寫入LCD
Init_DS1302(); //將1302初始化
while(1)
{
ReadValue = ReadSet1302(0x81); //從秒寄存器讀數據
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//將讀出數據轉化
DisplaySecond(second); //顯示秒
ReadValue = ReadSet1302(0x83); //從分寄存器讀
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayMinute(minute); //顯示分
ReadValue = ReadSet1302(0x85); //從分寄存器讀
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayHour(hour); //顯示小時
ReadValue = ReadSet1302(0x87); //從分寄存器讀
day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayDay(day); //顯示日
ReadValue = ReadSet1302(0x89); //從分寄存器讀
month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayMonth(month); //顯示月
ReadValue = ReadSet1302(0x8d); //從分寄存器讀
year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayYear(year); //顯示年
}
}
改改 就是你的了
4. 時鍾程序單片機
muteM EQU 10h ;靜音鍵 鬧鈴開/關
timerT EQU 0Ch ;菜單鍵 進入/退出設置狀態
leftL EQU 46h ;左移鍵
rightR EQU 47h ;右移鍵
upU EQU 19h ;增加鍵
downD EQU 1dh ;減少鍵
d_off EQU 16H ;顯示鍵 LED數碼管顯示/關閉
recall EQU 44H ;日歷鍵 DS1302初始化操作
K_on BIT P3.0 ;鬧鈴輸出
LED1 BIT P3.3
LED2 BIT P3.4
LED3CLK BIT P3.5 ;DS1302
LED4IO BIT P3.7
RST BIT P3.1
SECOND EQU 60H
;60H 秒
;61h 分
;62h 時
;63h 日
;64h 月 ;65h DAY
;66h 年
;6Ah 鬧分 from 00(1302)
;6BH 鬧時 from 01(1302)
;***************************
ORG 0000H
AJMP START
ORG 0003H
LJMP S_INT ;IRF
ORG 000BH ;200Us
LJMP P_INT ;
ORG 001BH ;display LED
LJMP DISPLAY
;**************************** ;main program
ORG 0030H
START: CLR RST
MOV SP,#2AH
SETB 05H
CLR 06H
SETB 07H;CLR 07H
CLR 08H
CLR 09H
CLR 0AH
CLR 0BH
CLR 0CH
SETB 0DH
CLR 0EH
CLR 0FH
CLR 10H
CLR 11H
MOV R2,#00H ;
MOV R3,#00H ;
MOV TMOD,#12H
MOV TL1,#0e5H ;wait
MOV TH1,#0BeH
MOV TH0,#3FH ;200uS 3f
MOV TL0,#3FH
SETB ET0
SETB ET1
setb pt0
SETB TR0
SETB TR1
SETB IT0 ;
SETB EX0 ;
CLR PX0 ;LCALL SET1302 ;初始化
MOV R1,#0C1H ;取定時參數從1302中
acall T_6061
MOV 6AH,A ;M
MOV R1,#0C3H
ACALL T_6061
MOV 6BH,A ;H
MOV 61H,#0
MOV 62H,#0
SETB EA
sjmp $
;********************************
DISPLAY: PUSH ACC
PUSH PSW
MOV TL1,#0e0H ;wait how long to display (20ms)
MOV TH1,#0b0H
MOV dptr,#tab1
JB 0EH,DIS2
JB 0FH,DIS3
JB 10H,DIS4
JB 11H,DIS5
JNB 0DH,D_OUT
JNB 08H,D_GO ;定時到時,顯示閃爍
JNB 07H,D_OUT
D_G MOV DPTR,#TAB1
MOV A,62H
ANL A,#0FH
MOV B,A
MOV A,62H
SWAP A
ANL A,#07H
MOVC A,@A+DPTR
MOV P1,A
CLR LED1
LCALL DL2M
SETB LED1
MOV A,B
MOVC A,@A+DPTR
MOV C,07H
MOV acc.7,C ;秒燈閃爍
MOV P1,A
CLR LED2
LCALL DL2M
SETB LED2
MOV dptr,#tab2 ;倒裝LED欄位表
MOV A,61H
ANL A,#0FH
MOV B,A
MOV A,61H
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV C,07H
MOV acc.6,C ;秒燈閃爍
MOV P1,A
CLR LED3CLK
LCALL DL2M
SETB LED3CLK
MOV dptr,#tab1
MOV A,B
MOVC A,@A+DPTR
MOV C,06H
cpl c
MOV acc.7,C ;鬧鈴指示燈
MOV P1,A
CLR LED4IO
LCALL DL2M
SETB LED4IO
D_OUT: SETB TR1
POP PSW
POP ACC
RETI
;*********************
DIS2: AJMP DIS_2
DIS3: AJMP DIS_3
DIS4: AJMP DIS_4
DIS5: AJMP DIS_5
;********************
DIS_2: MOV dptr,#tab1 ;顯示設置小時
MOV 6FH,62H
ACALL BCD_HEX
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV P1,A
CLR LED1
LCALL DL2M
SETB LED1
MOV A,B
MOVC A,@A+DPTR
MOV P1,A
CLR LED2
LCALL DL2M
SETB LED2
SETB TR1
POP PSW
POP ACC
RETI
;*****************
DIS_3: MOV DPTR,#TAB2 ;顯示設置分
MOV 6FH,61H
ACALL BCD_HEX
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV P1,A
CLR LED3CLK
LCALL DL2M
SETB LED3CLK
MOV A,B
MOV DPTR,#TAB1
MOVC A,@A+DPTR
MOV P1,A
CLR LED4IO
LCALL DL2M
SETB LED4IO
SETB TR1
POP PSW
POP ACC
RETI
;*****************
DIS_4: MOV dptr,#tab1 ;顯示設置鬧時
JNB 07H,D4_OUT ;顯示時閃爍
MOV A,6BH
MOV B,#0AH
DIV AB
MOVC A,@A+DPTR
MOV P1,A
CLR LED1
LCALL DL2M
SETB LED1
MOV A,B
MOVC A,@A+DPTR
MOV P1,A
CLR LED2
LCALL DL2M
SETB LED2
D4_OUT: SETB TR1
POP PSW
POP ACC
RETI
;***********************
DIS_5: MOV DPTR,#TAB2
JNB 07H,D5_OUT ;顯示時閃爍
MOV A,6AH ;顯示設置鬧分
MOV B,#0AH
DIV AB
MOVC A,@A+DPTR
MOV P1,A
CLR LED3CLK
LCALL DL2M
SETB LED3CLK
MOV DPTR,#TAB1
MOV A,B
MOVC A,@A+DPTR
MOV P1,A
CLR LED4IO
LCALL DL2M
SETB LED4IO
D5_OUT: SETB TR1
POP PSW
POP ACC
RETI
;*****************************
DL2M: MOV 43H,#14H ; every LED(2ms)
DL2: MOV 44H,#14H
DL1: NOP
NOP
DJNZ 44H,DL1
DJNZ 43H,DL2
RET
;************************定時讀取1302時間及判斷鬧鈴時間是否到*******
P_INT: PUSH ACC
PUSH PSW
INC R2
CJNE R2,#250D,P_OUT
MOV R2,#00H
INC R3
CJNE R3,#10D,P_OUT
MOV R3,#00H
CPL 07H
MOV P1,#0FFH
ACALL R_1302
OUT: JNB 06H,P_OUT
MOV A,6BH
MOV B,#10
DIV AB
SWAP A
ADD A,B
CJNE A,62H,PP_OUT
MOV A,6AH
MOV B,#10
DIV AB
SWAP A
ADD A,B
CJNE A,61H,PP_OUT
SETB 08H ;定時到標志
MOV C,07H
cpl c
MOV K_ON,C
P_OUT: POP PSW
POP ACC
RETI
PP_OUT: SETB K_ON
CLR 08H
POP PSW
POP ACC
RETI
;************************有接收到遙控器信號*******
S_INT:CLR EA
PUSH ACC
PUSH PSW
PUSH DPH
PUSH DPL
PUSH 02H
PUSH 03H
MOV R6,#10D ;
SB: ACALL YS1
JB P3.2,EXIT
DJNZ R6, SB
JNB P3.2, $ ;
ACALL YS2 ;
JB P3.2,EXIT
MOV R1,#1AH ;
MOV R2,#4D
PP: MOV R3,#8D
JJJJ: JNB P3.2,$
ACALL YS1
MOV C,P3.2
JNC UUU
JB P3.2,$
UUU: MOV A,@R1
RRC A
MOV @R1,A
DJNZ R3,JJJJ
INC R1
DJNZ R2,PP
;-------------------------------------
MOV A,1AH ;
XRL A,#40h ;判斷1AH的值是否等於遙控器低8位地址(40h)
JNZ EXIT ;
MOV A,1bH
XRL A,#0bfh ;再判斷高8位地址是否正確(0bfh)
JNZ EXIT
MOV A,1CH
CPL A
XRL A,1DH ;將1CH的值取反後和1DH比較 不同則無效丟棄(核對數據是否准確)
JNZ EXIT
ACALL DO ;相應按鍵的處理
EXIT: SETB EA
POP 03H
POP 02H
POP DPL
POP DPH
POP PSW
POP ACC
RETI
;--------------------delay-----------------------
YS1: MOV 70H,#16D ;延時1
D1: MOV 71H,#21D
DJNZ 71H,$
DJNZ 70H,D1
RET
YS2: MOV 70H,#09D ;延時2
D2: MOV 71H,#220D
DJNZ 71H,$
DJNZ 70H,D2
RET
;---------------------------------------------------------
TAB: DB 00H,01H,02H,03H,04H,05H,06H,07H,08H,09H ;TAB1 LED數碼管顯示表 TAB遙控器鍵值表(未用)
;TAB1: DB 3FH,11H,5EH,5BH,71H,6BH,6FH,19H,7FH,7bH,77H,7CH,39H,5EH,79H,71H
tab1: DB 0C0H,0F9H,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h,88h,83h,0a7h,0a1h,86h,8EH
TAB2: DB 0c0H,0f9H,64H,70H,59H,52H,42H ;倒裝LED段碼表
;0CH 為設置標志,0DH為全顯示標志,0EH為顯示設置小時標志,0FH為顯示設置分標志
;10H 為顯示設置鬧時標志,11H為顯示設置鬧分標志
;增加鬧時靜音功能
;mute-10h,timer-0eh,left-46h,right-47h,up-19h,down-1dh
D MOV A,1CH
CJNE A,#TIMERT,REDO ;代碼不是設置/退出鍵
JNB 0CH,SET1 ;是,則進入
CLR 0CH ;是,已經進入,則退出
SETB 0DH ;恢復正常顯示
CLR 0EH
CLR 0FH
CLR 10H
CLR 11H
RET
SET1: SETB 0CH
SETB 0EH
CLR 0DH
CLR 0FH
CLR 10H
CLR 11H
RET
RED CJNE A,#MUTEM,REDO1 ;不是設置鍵的處理REDO1,2,3,4...
LJMP MUTE ;MUTE?
REDO1: CJNE A,#D_OFF,DO_SET2
LJMP DIS_OFF ;關閉顯示
DO_SET2:JB 0CH,SET2 ;時間設置的處理
RET
SET2: CJNE A,#UPU,SET2A
LJMP INC1 ;+加(^)
SET2A: CJNE A,#DOWND,SET2B
LJMP DEC2 ;- 減
SET2B: CJNE A,#RIGHTR,SET2C
LJMP RIGHT ;RIGHT右移(>)
SET2C: CJNE A,#LEFTL,SET2D LJMP LEFT ;LEFT左移(<)
SET2D: CJNE A,#RECALL,SET2EXT ;DS1302初始化
LJMP SET1302
SET2EXT:RET
;--------------------------------INC------------------------
INC1: JB 0EH,INCH
JB 0FH,INCM
JB 10H,INC_H
JB 11H,INC_M
RET
INC_H: INC 6BH ;鬧鍾小時增加
MOV A,6BH
CJNE A,#24D,INCH3
MOV 6BH,#0
INCH3: MOV R1,#0C2H
MOV R0,6BH
ACALL SETONE ;寫入DS1302
RET
INC_M: INC 6AH ;鬧鍾分增加
MOV A,6AH
CJNE A,#60D,INCH4
MOV 6AH,#0
INCH4: MOV R1,#0C0H
MOV R0,6AH
ACALL SETONE ;
RET
INCH: ;INC 62H ;
MOV 6FH,62H
ACALL BCD_HEX
INC A
CJNE A,#24D,INCH1
MOV A,#0
INCH1: MOV 6FH,A
ACALL HEX_BCD
MOV 62H,A
MOV R1,#84H
MOV R0,62H
ACALL SETONE ;
RET
INCM: ;INC 61H ;
MOV 6FH,61H
ACALL BCD_HEX
INC A
CJNE A,#60D,INCH2
MOV A,#0
INCH2: MOV 6FH,A
ACALL HEX_BCD
MOV 61H,A
MOV R1,#82H
MOV R0,61H
ACALL SETONE ;
RET
;----------------------------------DEC----------------------
DEC2: JB 0EH,DECH
JB 0FH,DECM
JB 10H,DEC_H
JB 11H,DEC_M
RET
DECH: MOV 6FH,62H
ACALL BCD_HEX
DEC A
CJNE A,#0FFH,DECH1
MOV A,#23
DECH1: MOV 6FH,A
ACALL HEX_BCD
MOV 62H,A
MOV R1,#84H
MOV R0,62H
ACALL SETONE
RET
DECM: MOV 6FH,61H
ACALL BCD_HEX
DEC A
CJNE A,#0FFH,DECM1
MOV A,#59
DECM1: MOV 6FH,A
ACALL HEX_BCD
MOV 61H,A
MOV R1,#82H
MOV R0,61H
ACALL SETONE
RET
DEC_H: DEC 6BH
MOV A,6BH
CJNE A,#0FFH,DECH3
MOV 6BH,#23D
DECH3: MOV R1,#0C2H
MOV R0,6BH
ACALL SETONE
RET
DEC_M: DEC 6AH
MOV A,6AH
CJNE A,#0FFH,DECH4
MOV 6AH,#59D
DECH4: MOV R1,#0C0H
MOV R0,6AH
ACALL SETONE
RET
;--------------------------------RIGHT----------------------
RIGHT: JB 0EH,RIGHT1
JB 0FH,RIGHT2
JB 10H,RIGHT3
JB 11H,RIGHT4
RET ;右移
RIGHT1: CLR 0EH
SETB 0FH
RET
RIGHT2: CLR 0FH
SETB 10H
RET
RIGHT3: CLR 10H
SETB 11H
RET
RIGHT4: CLR 11H
SETB 0EH
RET
;--------------------------------LEFT-----------------------
LEFT: JB 0EH,LEFT1
JB 0FH,LEFT2
JB 10H,LEFT3
JB 11H,LEFT4
RET ;左移
LEFT1: SETB 11H
CLR 0EH
RET
LEFT2: SETB 0EH
CLR 0FH
RET
LEFT3: SETB 0FH
CLR 10H
RET
LEFT4: SETB 10H
CLR 11H
RET
;------------------------------MUTE--------------
MUTE: setb k_ON
CPL 06H ;靜音
CLR 08H
RET
;-----------------------------DISPLAY OFF--------
DIS_OFF:CLR ET1
CPL 05H
JNB 05H,REDORE
SETB ET1
REDORE: RET
;------------------------------------初始化1302
SET1302: CLR RST ;2002年1月1日12:00:00
CLR LED3CLK
MOV SECOND,#0
MOV 61H,#0
MOV 62H,#18 ;
MOV 63H,#1
MOV 64H,#1
MOV 65H,#1
MOV 66H,#2
SETB RST
MOV A,#8EH
LCALL R_BIT
MOV A,#00H
LCALL R_BIT
SETB LED3CLK
CLR RST
MOV R0,#SECOND
MOV R7,#7
MOV R1,#80H
SET1302A:CLR RST
CLR LED3CLK
SETB RST
MOV A,R1
LCALL R_BIT
MOV A,@R0
LCALL R_BIT
INC R0
INC R1
INC R1
SETB LED3CLK
CLR RST
DJNZ R7,SET1302A
CLR RST
CLR LED3CLK
sETB LED3CLK
nop
CLR RST
nop
clr led3clk
SETB RST
MOV A,#90H
LCALL R_BIT
MOV A,#10100101B ;充電器設置
LCALL R_BIT
SETB LED3CLK
CLR RST
CLR LED3CLK
SETB RST
MOV A,#8EH
LCALL R_BIT
MOV A,#80H
LCALL R_BIT
SETB LED3CLK
CLR RST
RET
;----------------------讀取一RAM ------
T_6061: CLR RST
CLR LED3CLK
SETB RST
MOV A,R1
LCALL R_BIT
LCALL W_BIT
SETB LED3CLK
CLR RST
RET
;-----------------------------
R_1302: MOV R0,#SECOND
MOV R7,#7
MOV R1,#81H
R_1302A: CLR RST
CLR LED3CLK
SETB RST
MOV A,R1
LCALL R_BIT
LCALL W_BIT
MOV @R0,A
INC R0
INC R1
INC R1
SETB LED3CLK
CLR RST
DJNZ R7,R_1302A
RET
;------------------R_BIT------------------
R_BIT: MOV R4,#8
R_BIT1: RRC A
MOV LED4IO,C
SETB LED3CLK
CLR LED3CLK
DJNZ R4,R_BIT1
RET
;-------------------W_BIT-----------------------
W_BIT: MOV R4,#8
W_BIT1: MOV C,LED4IO
RRC A
SETB LED3CLK
CLR LED3CLK
DJNZ R4,W_BIT1
RET
;--------------------------------------------------
BCD_HEX:
MOV A,6FH
ANL A,#0FH
MOV B,A
MOV A,6FH
MOV 6FH,B
SWAP A
ANL A,#0FH
MOV B,#0AH
MUL AB
ADD A,6FH
;MOV 6FH,A
RET
HEX_BCD:
MOV A,6FH
MOV B,#10
DIV AB
SWAP A
ADD A,B
;MOV 6FH,A
RET
;-----寫一地址---R1 為地址,R0 為數據----------
SETONE: CLR LED3CLK
CLR RST
CLR LED3CLK
NOP
SETB RST
MOV A,#8EH
LCALL R_BIT
MOV A,#00H
LCALL R_BIT
SETB LED3CLK
CLR RST
CLR LED3CLK
NOP
CLR RST
CLR LED3CLK
SETB RST
MOV A,R1
LCALL R_BIT
MOV A,R0
LCALL R_BIT
NOP
SETB LED3CLK
CLR RST
NOP
NOP
CLR RST
CLR LED3CLK
SETB RST
MOV A,#8EH
LCALL R_BIT
MOV A,#80H
LCALL R_BIT
SETB LED3CLK
CLR RST
RET
5. 求一個51單片機定時鬧鍾程序。要C語言。能夠調時間
我來發一個C語言51單片機時鍾程序,希望能幫到你
/*程序功能:帶定時鬧鈴時鍾*/
/*---------------------------------------------------------------*/
#include<AT89X51.H>/*包含器件配置文件*/
#defineucharunsignedchar
#defineuintunsignedint
charDATA_7SEG[10]={0xC0,0xF9,0xA4,0xB0,0x99,
0x92,0x82,0xF8,0x80,0x90,};/*0~9的數碼管段碼*/
ucharhour=0,min=0,sec=0;/*時、分、秒單元清零*/
uchardeda=0;/*5mS計數單元清零*/
bitd_05s=0;/*0.5秒標志*/
ucharset=0;/*模式設定標志*/
ucharm=0;
ucharflag=0;/*RAM掉電標志*/
voiddelay(uintk);/*延時?函數*/
voidconv();/*走時單元轉換*/
voiddisp();/*走時時間顯示?函數*/
/*------------------------走時?函數部分----------------------*/
/*定時器T05mS初始化*/
voidinit_timer()
{
TMOD=0x01;
TH0=-(4800/256);
TL0=-(4800%256);
IE=0x82;
TR0=1;
}
/*---------------------------------*/
/*5mS定時中斷服務?函數*/
voidT0_srv(void)interrupt1
{
TH0=-(4800/256);
TL0=-(4800%256);
deda++;
}
/*----------------------------------*/
/*時、分、秒單元及走時單元轉換*/
voidconv()
{
if(deda<=100)d_05s=0;
elsed_05s=1;
if(deda>=200){sec++;deda=0;}
if(sec==60){min++;sec=0;}
if(min==60){hour++;min=0;}
if(hour==24){hour=0;}
}
/*------------------------顯示?函數部分----------------------*/
/*走時時間顯示?函數*/
voiddisp()
{
P0=DATA_7SEG[hour/10];P2=0xf7;delay(1);
P0=DATA_7SEG[hour%10];P2=0xfb;delay(1);
if(d_05s==1){if(P2_2==0)P0_7=0;elseP0_7=1;}
delay(1);
P0=DATA_7SEG[min/10];P2=0xfd;delay(1);
P0=DATA_7SEG[min%10];P2=0xfe;delay(1);
}
/*----------------------調整時間?函數部分-------------------*/
/*調整走時時間*/
voidset_time()
{ucharm;
if(P2_5==0)delay(1);
if(P2_5==0)hour++;
if(hour==24)hour=0;
for(m=0;m<30;m++)
{
disp();
if(P2_2==0)P0_7=0;
elseP0_7=1;
delay(1);
}
if(P2_6==0)delay(1);
if(P2_6==0)min++;
if(min==60)min=0;
for(m=0;m<30;m++)
{
disp();
if(P2_2==0)P0_7=0;
elseP0_7=1;
delay(1);
}
}
/*------------------按鍵掃描、延時等?函數部分-------------------*/
/*走時時間程序?函數*/
voidtime()
{
conv();/*走時單元轉換?函數*/
disp();/*走時時間顯示?函數*/
}
/*------------------------------------*/
/*掃描按鍵?函數*/
voidscan_key()
{
delay(1);
if(P2_4==0)set++;
if(set>=2)set=0;
if(set==1)flag=0x55;
F0:if(P2_4==0)gotoF0;/*按鍵未釋放,在此等候*/
}
/*------------------------------*/
/*延時?函數*/
voiddelay(uintk)
{
uinti,j;
for(i=0;i<k;i++){
for(j=0;j<121;j++)
{;}}
}
/*-----------------------主函數-------------------------*/
/*主函數*/
voidmain()
{
init_timer();/*定時器T0初始化*/
while(1)/*無限循環*/
{
if(P2_4==0)scan_key();/*有按鍵,調用按鍵掃描?函數*/
switch(set)/*根據set鍵值散轉*/
{
case0:time();break;/*走時時間程序*/
case1:set_time();break;/*走時時間調整*/
default:break;/*其它退出*/
}
if(flag!=0x55)/*判斷掉電標志*/
{
P0=0xc0;P2=0xc0;delay(100);
P2=0xff;delay(400);
}
}
}