|
本帖最後由 antlu 於 2012-10-16 02:28 AM 編輯
上次把 電子遊戲機的板子切下來之後就一直想要把它拿來使用,裡面用的是 MC14511和 ULN2003,卻發生了許多插曲!! 因為我買了兩片所以可以相互驗證問題的所在!! 首先 MC14511 是把 BCD轉成七段顯示,而以前的七段顯示使用查表法把各段用8BIT送出,而這次的板子裡面有兩個,所以直接把BCD送到 DATA PORT就可以了!! 不料16進位與10進位還需要作一些轉換,還有 第一片板子顯示的時候居然出了"怪"現象,正常計數亂顯示!! 搞的我信心大失,於是決定切另一片板子,(這又花了一些時間),之後印證了第一片板子的 MC14511可能出了問題,但是第二片板子亮度卻變的很弱!! 這幾天就是找時間買新的 MC14511(沒買到!!),後來把MC14511 重新"裝回去"居然又正常了!!(觀察中...) 還有發生的怪問題是 "時間不準","時間凍結","時間停頓" 的現象,時間不準 經過更換了一個(都是舊的) 32768 之後解決了,卻會 時間偶發凍結的現象後來更換了另一個 32768石英之後還把洞洞版的絕緣清除了一下,時間不再凍結了!! 但是電源拔掉之後時間好像會停頓,目前不知道原因!! 先前也在其他地方發生過(目前懷疑是 DS1302出問題!!) 最後!! 就是幫她找一個家作一個"殼",剛好之前在"大創39圓店"買了一個壓克力容器,非常適合就把它組裝起來... 另外一個板子也一併給裝箱!!
電阻放在IC座下方
3.3V轉換
程式
/*-----------------------------------------------
20121008 要改寫程式lcm改為14511 7段加上DS1302 作為 REALTIME CLOCK, 當 GPS信號為 A 時候 更新 DS1302裡面的資料,平常由 DS1302來計時,要校正的時候,只要把 GPS 供電,這時候GPS信號達到水準就可以.
強迫校時 時間約 25分鐘讀取 gps 訊號 baud rate 4800 1010 發生 字段顯示異常!! 可能是硬體問題!! 層別是顯示板不良!!
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
sbit SCK=P1^4; //ds1302 時鐘
sbit SDA=P1^5;
sbit RST=P1^6;
sbit FCUPSW=P1^7;//強迫gps 更新ds1302時間LO動作
bit ReadTimeFlag;//定义读时间标志
bit SetFlag; //更新时间标志位
bit rec;
unsigned char REV_DATA,Gok;//GPS_ST 存放 a v 狀態
unsigned char FCUDT;//強迫更新時間計時 15分
unsigned char CLCK[6];//GPS hr min sec store
unsigned char GPS_AV;//GPS 信號 A強 V弱
unsigned char YMD[6];//年月日存放
unsigned char dca,dcb,dcc,ms2,ms3;// time counter SEC MIN HR
unsigned char time_buf1[8];//空年月日时分秒周 extern
unsigned char TempData[12];
unsigned char Ds1302_Read_Byte(unsigned char addr) ;
unsigned char code Digi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//
//----------------************----------------------------
#define DataPort P0
#define ScanPort P2
//DS1302复位脚
#define RST_CLR RST=0//电平置低
#define RST_SET RST=1//电平置高
#define IO_CLR SDA=0//电平置低
#define IO_SET SDA=1//电平置高
#define IO_R SDA //电平读取
#define SCK_CLR SCK=0//时钟信号
#define SCK_SET SCK=1//电平置高
#define ds1302_sec_add 0x80 //秒数据地址
#define ds1302_min_add 0x82 //分数据地址
#define ds1302_hr_add 0x84 //时数据地址
#define ds1302_date_add 0x86 //日数据地址
#define ds1302_month_add 0x88 //月数据地址
#define ds1302_day_add 0x8a //星期数据地址
#define ds1302_year_add 0x8c //年数据地址
#define ds1302_control_add 0x8e //控制数据地址
#define ds1302_charger_add 0x90
#define ds1302_clkburst_add 0xbe
extern unsigned char time_buf[8] ;//空年月日时分秒周
void Ds1302_Write_Byte(unsigned char addr, unsigned char d);
void Ds1302_Write_Time(void) ;
void Ds1302_Read_Time(void) ;
void Ds1302_Init(void);
void DelayMs(unsigned char t);
void Init_Timer0(void);//定时器初始化
void UART_Init(void);
void GPS_Write(void);//把 GPS 的時間寫入 DS1302
void Display(void);//MC14511 轉換 65536' 06 55 36
/*------------------------------------------------
串口通讯初始化
------------------------------------------------*/
void UART_Init(void)
{
SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装----4800 only
TH1 = 0xfa; // TH1: 重装值 GPS 4800 波特率 晶振 11.0592MHz ---4800 only
// T2CON = 0x34; // timer2 parameter set ---38400 only
// RCAP2H = 0xff; //set uart baud rate 38400---38400 only
//RCAP2L = 0xf7;// --------------------------38400 only
// ET2 = 1;// enable timer2 overflow flag -----38400 only
//TR2 = 1;// timer2 enable ------------------38400 only
TR1 = 1; // TR1: timer 1 打开 ------------------ ?4800 only
EA = 1; //打开总中断
ES = 1; //打开串口中断
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00; //给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-3010)/256; //重新赋值 3ms
TL0=(65536-3010)%256;
ms2++;// 3ms setflag
Display();
if(ms2>150)//150*3=450
{
ms2=0;
ReadTimeFlag=1;
ms3++;//----450ms-----------------
}
if(ms3>3)// .45*4=1.8s
{
ms3=0;
dca++;//dca=1.8sec count
}
if(dca>34)//1min
{
dcb++;
dca=0;
if(FCUPSW==0)//P1^1 sw lo動作
{
FCUDT++;//強迫更新時間 108sec
}
}
if(dcb>59)//1hr
{
dcb=0;
}
}
//GPS 部分
void UART_SER (void) interrupt 4 //來自GPS 程式
{
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
REV_DATA =SBUF; //读入缓冲区的值
rec=1;
}
if(TI) //如果是发送标志位,清零
TI=0;
}
void CLCKFL(unsigned char CLCKCT)//填入6個時 分 秒資料
{
unsigned char ct=0;
rec=0;//必要的
while(CLCKCT>ct)//儲存數量
{
while(rec==0);
if(rec==1)
{
CLCK[ct]=REV_DATA-0x30;
rec=0;
ct++;
}
}
}
//0819 填入6個年月日資料
void YMDFL(unsigned char YMDCT)
{
unsigned char yt=0;
rec=0;//必要的
while(YMDCT>yt)//儲存數量
{
while(rec==0);
if(rec==1)
{
YMD[yt]=REV_DATA-0x30;
rec=0;
yt++;
}
}
}
//0819 跳過幾個逗號
void JPDM(unsigned char DM)
{
rec=0;
while(DM)//>dmt
{
while(rec==0);
// if (rec==1)
{
if(REV_DATA == ',')
{
rec=0;
DM--;//dmt++
}
}
}
}
void GPS_Write(void)//把 GPS 的時間寫入 DS1302
{
time_buf1[3]=YMD[0]*10+YMD[1];//日
time_buf1[2]=YMD[2]*10+YMD[3];// 月
time_buf1[1]=YMD[4]*10+YMD[5];// 年
time_buf1[4]=CLCK[0]*10+CLCK[1];//HR
time_buf1[5]=CLCK[2]*10+CLCK[3];// min
time_buf1[6]=CLCK[4]*10+CLCK[5];// sec
Ds1302_Write_Time();
}
unsigned char Get_Gps(void)//改寫 gps 讀取程式 把 Gok=GPRMC_K() 取消
{
unsigned char TT;
if(rec==1)
{
if(REV_DATA == '$')
{
rec=0;
}
}
else
{
return 0;
}
while(rec==0);
if(REV_DATA == 'G')
{
rec=0;
}
while(rec==0);
if(REV_DATA == 'P')
{
rec=0;
}
while(rec==0);
if(REV_DATA == 'R')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
else
{
return 0;
}
while(rec==0);
if(REV_DATA == 'M')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
while(rec==0);
if(REV_DATA == 'C')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
while(rec==0);
if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
else
{
return 0;
}
CLCKFL(6);//取 時分秒
JPDM(1);
while(rec==0);
{
GPS_AV = REV_DATA;
}
JPDM(7);//跳過8個逗號
YMDFL(6);//取 年月日
TT=CLCK[0]*10+CLCK[1]+8;
if(TT>23)
TT-=24;
CLCK[0]=TT/10;
CLCK[1]=TT%10;
return 1;
}
/*
void DelayUs2x(unsigned char t)
{
while(--t);
}
void DelayMs(unsigned char t)
{
while(t--)
{
DelayUs2x(245);
DelayUs2x(245);
}
}
*/
unsigned char time_buf[8] ; //空年月日时分秒周
/*------------------------------------------------
向DS1302写入一字节数据
------------------------------------------------*/
void Ds1302_Write_Byte(unsigned char addr, unsigned char d)
{
unsigned char i;
RST_SET;
//写入目标地址:addr
addr = addr & 0xFE; //最低位置零
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
//写入数据:d
for (i = 0; i < 8; i ++)
{
if (d & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
SCK_CLR;
d = d >> 1;
}
RST_CLR; //停止DS1302总线
}
/*------------------------------------------------
从DS1302读出一字节数据
------------------------------------------------*/
unsigned char Ds1302_Read_Byte(unsigned char addr)
{
unsigned char i;
unsigned char temp;
RST_SET;
//写入目标地址:addr
addr = addr | 0x01;//最低位置高
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
//输出数据:temp
for (i = 0; i < 8; i ++)
{
temp = temp >> 1;
if (IO_R)
{
temp |= 0x80;
}
else
{
temp &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
RST_CLR; //停止DS1302总线
return temp;
}
/*------------------------------------------------
向DS1302写入时钟数据
------------------------------------------------*/
void Ds1302_Write_Time(void)
{
unsigned char i,tmp;
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf1/10;
time_buf=time_buf1%10;
time_buf=time_buf+tmp*16;
}
Ds1302_Write_Byte(ds1302_control_add,0x00); //关闭写保护
Ds1302_Write_Byte(ds1302_sec_add,0x80); //暂停
//Ds1302_Write_Byte(ds1302_charger_add,0xa9); //涓流充电
Ds1302_Write_Byte(ds1302_year_add,time_buf[1]); //年
Ds1302_Write_Byte(ds1302_month_add,time_buf[2]); //月
Ds1302_Write_Byte(ds1302_date_add,time_buf[3]); //日
Ds1302_Write_Byte(ds1302_day_add,time_buf[7]); //周
Ds1302_Write_Byte(ds1302_hr_add,time_buf[4]); //时
Ds1302_Write_Byte(ds1302_min_add,time_buf[5]); //分
Ds1302_Write_Byte(ds1302_sec_add,time_buf[6]); //秒
Ds1302_Write_Byte(ds1302_day_add,time_buf[7]); //周
Ds1302_Write_Byte(ds1302_control_add,0x80); //打开写保护
}
/*------------------------------------------------
从DS1302读出时钟数据
------------------------------------------------*/
void Ds1302_Read_Time(void)
{
unsigned char i,tmp;
time_buf[1]=Ds1302_Read_Byte(ds1302_year_add); //年
time_buf[2]=Ds1302_Read_Byte(ds1302_month_add); //月
time_buf[3]=Ds1302_Read_Byte(ds1302_date_add); //日
time_buf[4]=Ds1302_Read_Byte(ds1302_hr_add); //时
time_buf[5]=Ds1302_Read_Byte(ds1302_min_add); //分
time_buf[6]=(Ds1302_Read_Byte(ds1302_sec_add))&0x7F;//秒
time_buf[7]=Ds1302_Read_Byte(ds1302_day_add); //周
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf/16;
time_buf1=time_buf%16;
time_buf1=time_buf1+tmp*10;
}
}
/*------------------------------------------------
DS1302初始化
------------------------------------------------*/
void Ds1302_Init(void)
{
RST_CLR; //RST脚置低
SCK_CLR; //SCK脚置低
Ds1302_Write_Byte(ds1302_sec_add,0x00);
}
void Normal_dsp(void)//正常顯示模式 放在主程式裡
{
if(ReadTimeFlag==1) //定时读取ds1302 定时时间到 则标志位置1,处理过时间参数标志位清零
{
ReadTimeFlag=0; //标志位清零
Ds1302_Read_Time();//读取时间参数
//for 14511 need add BCD transfer
TempData[0]=0x20;
TempData[1]=time_buf1[1]/10<<4|time_buf1[1]%10;//y
TempData[2]=time_buf1[2]/10<<4|time_buf1[2]%10;//time_buf1[2]/10<<4|time_buf1[2]%10;
TempData[3]=time_buf1[3]/10<<4|time_buf1[3]%10;//time_buf1[3]/10<<4|time_buf1[3]%10; //m //加入"-"
TempData[4]=time_buf1[4]/10<<4|time_buf1[4]%10;
TempData[5]=time_buf1[5]/10<<4|time_buf1[5]%10; //d
TempData[6]=time_buf1[6]/10<<4|time_buf1[6]%10;
}
}
void Display(void)//MC14511 轉換 65536' 06 55 36
{
unsigned char disi;
DataPort=TempData[disi]; //取位码 年 月 日 時 分 秒
ScanPort=Digi[disi]; //取显示数据,段码
disi ++;
if(7== disi) //检测8位扫描完全结束
disi =0;
}
void main (void)
{
Init_Timer0(); //定时器0初始化
Ds1302_Init(); //ds1302初始化
UART_Init(); //串口初始化
Ds1302_Read_Time(); //首次读取时间
//if((time_buf1[2]+time_buf1[7])==0) //如果所有参数都为0,写入一个初始值
// Ds1302_Write_Time();
while (1) //主循环
{
Gok= Get_Gps();//取GPS信號
if(Gok==1)
{
if(GPS_AV=='A')
{
GPS_Write();
Gok=0;
}
}
if(FCUDT==30)//此一動作為長久收不到4個衛星信號強迫寫入時間30min.
{
GPS_Write();
FCUDT=0;
}
Normal_dsp();//一般正常的顯示
}
}
|
評分
-
2
查看全部評分
-
|