專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開發(fā)工具、應(yīng)用測試 完善的開發(fā)代碼案例庫分享
從全面的產(chǎn)品導(dǎo)入到強(qiáng)大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無限潛能!
深圳市英銳恩科技有限公司:臺(tái)灣麥肯單片機(jī)(Micon MDT單片機(jī))亞太地區(qū)A級(jí)代理商
QLdsPIC3]實(shí)時(shí)時(shí)鐘[C30+dsPIC30F6014A]
//實(shí)驗(yàn)?zāi)康模菏煜r(shí)鐘芯片PCF8583以及IIC通信
//軟件規(guī)劃:
// 1,通過按下按鍵K7往時(shí)鐘芯片內(nèi)寫入預(yù)設(shè)時(shí)間和日期為,包括毫秒、秒、分、時(shí)、日、月、年、星期
// 2、通過查詢時(shí)鐘芯片觸發(fā)的中斷讀取時(shí)間(1秒執(zhí)行一次)
// 3、時(shí)間和日期送LCD1602顯示,顯示格式如下:
// ------------------------
// | HH:MM:SS |
// | Y:y M:mm D:dd W |
// ------------------------
//硬件要求:撥碼開關(guān)S13全部置ON
// 撥碼開關(guān)S2第2位置ON
// 跳線J18全部接通
#include //dsPIC30F6014標(biāo)準(zhǔn)頭文件
_FOSC(CSW_FSCM_OFF & XT_PLL4); //4倍頻晶振,F(xiàn)ailsafe 時(shí)鐘關(guān)閉
_FWDT(WDT_OFF); //關(guān)閉看門狗定時(shí)器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉電復(fù)位禁止,MCLR復(fù)位使能。
_FGS(CODE_PROT_OFF); //代碼保護(hù)禁止
#define i_o PORTGbits.RG3 //定義DS1302的數(shù)據(jù)口
#define sclk PORTGbits.RG2 //定義DS1302的時(shí)鐘口
#define intr PORTAbits.RA12 //定義DS1302的復(fù)位口
#define rs LATBbits.LATB4 //定義LCD控制位(注意這里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e LATBbits.LATB6
// unsigned char time_rx;
unsigned char __attribute__((address(0x900))) rd_data[6]={0,0,0,0,0,0}; //定義接收寄存器
// LCD顯示數(shù)據(jù)
unsigned char __attribute__((address(0x920))) lcd[16]={' ',' ',' ',' ',0,0,':',0,0,':',0,0,' ',' ',' ',' '};
unsigned char __attribute__((address(0x940))) lcd1[16]={'Y',':',0,' ','M',':',0,0,' ','D',':',0,0,' ',' ',0};
//定義待設(shè)置的時(shí)間:豪秒、 秒、 分、 時(shí)、 日/年、 月/星期
const char table[]={ 0, 88, 88, 18 ,41 ,50};
// 0豪秒;58秒;58分;12時(shí) 0年29日 12月星期1
//****************************延時(shí)程序**************************************
void delay() //延時(shí)程序
{
int i; //定義整形變量
for(i=0;i<10;i++); //延時(shí)
}
//***************************寫PCF8583程序**********************************
void wr_data(unsigned char temp)
{
I2CTRN=temp; //數(shù)據(jù)送IIC的發(fā)送寄存器
while(!IFS0bits.MI2CIF); //等待發(fā)送完成
IFS0bits.MI2CIF=0;
}
//**************************等待總線空閑為空程序****************************
void finish()
{
while(!IFS0bits.MI2CIF); //等待總線空閑
IFS0bits.MI2CIF=0;
}
//*************************寫LCD程序****************************************
//寫一個(gè)字節(jié)數(shù)據(jù)函數(shù)
//在電平發(fā)生改變后需要插入一段延時(shí)時(shí)間,否則LCD反應(yīng)不過來。
void write(unsigned int x)
{
PORTD=x; //待顯示數(shù)據(jù)送PORTD口
delay();
rs=1; //該字節(jié)數(shù)據(jù)為數(shù)據(jù),而不是命令
delay();
rw=0; //此次操作為寫,而不是讀
delay();
e=0; //拉低使能信號(hào)
delay(); //保持使能信號(hào)為低一段時(shí)間
e=1; //拉高使能信號(hào),建立LCD操作所需要的上升沿
delay();
}
//********************LCD顯示設(shè)置函數(shù)**************************************
//在電平發(fā)生改變后需要插入一段延時(shí)時(shí)間,否則LCD反應(yīng)不過來。
void lcd_enable()
{
delay();
rs=0; //該字節(jié)數(shù)據(jù)為命令,而不是數(shù)據(jù)
delay();
rw=0; //此次操作為寫,而不是讀
delay();
e=0; //拉低使能信號(hào)
delay(); //保持使能信號(hào)為低一段時(shí)間
e=1; //拉高使能信號(hào),建立LCD操作所需要的上升沿
delay();
}
//**********************IIC初始化函數(shù)***************************************
void i2c_init()
{
TRISB=0X0000; //設(shè)置B口為輸出
TRISD=0X0000; //設(shè)置D口為輸出
TRISC=0XFFFF;
TRISG=0XFFFF;
I2CCON=0;
I2CSTAT=0;
I2CBRG=15; //400K
I2CCONbits.I2CEN=1; //使能IIC
}
//*********************LCD初始化函數(shù)**************************************
void lcd_init()
{
PORTD=0X1; //清除顯示
lcd_enable();
PORTD=0X38; //8位2行5*7點(diǎn)陣
lcd_enable();
PORTD=0X0e; //顯示開,光標(biāo)開,閃爍
lcd_enable();
PORTD=0X06; //文字不動(dòng),光標(biāo)右移
lcd_enable();
}
//*******************PCF8583中斷使能函數(shù)***********************************
void i2c_interrupt_init()
{
// IPC4=7; //優(yōu)先級(jí)別最高
IEC1bits.INT1IE=0; //使用查詢方式
IFS1bits.INT1IF=0; //清除中斷標(biāo)志位
INTCON2bits.INT1EP=1; //負(fù)邊沿觸發(fā)
I2CCONbits.SEN=1; //發(fā)送起始位
finish(); //等待完成
wr_data(0xa0); //發(fā)送控制命令和寫命令
wr_data(0); //寫8583的第0單元
wr_data(4); //寫入數(shù)據(jù)4(使能中斷功能)
I2CCONbits.RSEN=1; //發(fā)重啟動(dòng)位
finish(); //等待完成
wr_data(0xa0); //發(fā)送控制命令和寫命令
wr_data(8); //寫8583的第8單元
wr_data(9); //寫入數(shù)據(jù)9(計(jì)時(shí)中斷功能)
I2CCONbits.PEN=1; //發(fā)停止位
finish(); //等待完成
}
//***********************LCD顯示函數(shù)************************************
void lcd_display()
{
unsigned char i,j;
PORTD=0X80; /顯示地址
lcd_enable();
for(i=0;i<16;i++) //一共16字節(jié)數(shù)據(jù)
{
write(lcd[i]); //查表獲取數(shù)據(jù)并調(diào)用寫一個(gè)字節(jié)數(shù)據(jù)函數(shù)送LCD顯示
for(j=0;j<5;j++) //延時(shí)一段時(shí)間(主要是為了控制顯示的速度)
{delay();}
}
PORTD=0X00c0; //日期時(shí)間顯示地址
lcd_enable();
for(i=0;i<16;i++) //一共16字節(jié)數(shù)據(jù)
{
write(lcd1[i]); //查表獲取數(shù)據(jù)并調(diào)用寫一個(gè)字節(jié)數(shù)據(jù)函數(shù)送LCD顯示
for(j=0;j<5;j++) //延時(shí)一段時(shí)間(主要是為了控制顯示的速度)
{delay();}
}
}
//***********************設(shè)置初始時(shí)間函數(shù)******************************
void i2c_write()
{
unsigned char i;
I2CCONbits.SEN=1; //發(fā)送啟動(dòng)位
finish(); //等待完成
wr_data(0xa0); //發(fā)送控制命令和寫命令
wr_data(1); //待修改的8583起始單元地址(毫秒單元;地址自動(dòng)+1)
for(i=0;i<6;i++) //共修改6個(gè)單元(時(shí)間跟日期)
{
wr_data(table[i]); //查表寫數(shù)據(jù)
}
I2CCONbits.PEN=1; //發(fā)送停止位
finish(); //等待完成
}
//************************讀時(shí)間函數(shù)***********************************
void i2c_read()
{
unsigned char i;
I2CCONbits.SEN=1; //發(fā)送起始位
finish(); //等待完成
wr_data(0xa0); //發(fā)送控制命令和寫命令
wr_data(2); //讀時(shí)間的起始單元
I2CCONbits.RSEN=1; //發(fā)重啟動(dòng)位
finish(); //等待完成
wr_data(0xa1); //發(fā)送控制命令和讀命令
for(i=0;i<7;i++) //讀取時(shí)間
{
I2CCONbits.RCEN=1; //使能IIC的讀功能
rd_data[i]=I2CRCV; //保存讀取到的時(shí)間
finish(); //等待完成
I2CCONbits.ACKEN=1; //使能應(yīng)答功能
if(i==6) I2CCONbits.ACKDT=1; //不是最好一個(gè)數(shù)據(jù),應(yīng)答信號(hào)為0,繼續(xù)讀數(shù)據(jù)
else I2CCONbits.ACKDT=0; //做后一個(gè)數(shù)據(jù),應(yīng)答信號(hào)為1
while(!IFS0bits.MI2CIF);
IFS0bits.MI2CIF=0;
}
I2CCONbits.PEN=1; //發(fā)送停止位
finish(); //等待完成
}
//*************讀取時(shí)間轉(zhuǎn)換成BCD碼并存儲(chǔ)到LCD顯示緩沖單元*************
void hex2bcd()
{
lcd[11]=(rd_data[1]&0xf)+0x30; // 1/10 second
lcd[10]=(rd_data[1]>>4)+0x30; // second
lcd[8]=(rd_data[2]&0xf)+0x30; // 1/10 minute
lcd[7]=(rd_data[2]>>4)+0x30; // minute
lcd[5]=(rd_data[3]&0xf)+0x30; // 1/10 hour
lcd[4]=(rd_data[3]>>4)+0x30; // hour
lcd1[12]=(rd_data[4]&0xf)+0x30; // 1/10 date
lcd1[11]=((rd_data[4]>>4)&3)+0x30; // data
lcd1[2]=(rd_data[4]>>6)+0x30; // year
lcd1[7]=(rd_data[5]&0xf)+0x30; // 1/10 month
lcd1[6]=((rd_data[5]>>4)&1)+0x30; // month
lcd1[15]=(rd_data[5]>>5)+0x30; // weekday
}
//***********************主函數(shù)**************************************
int main(void)
{
i2c_init(); //系統(tǒng)初始化
lcd_init(); //LCD初始化
i2c_interrupt_init(); //芯片中斷使能
while(1)
{
while(!PORTCbits.RC3)
{
i2c_write(); //設(shè)置初始時(shí)間
while(!PORTCbits.RC3);
}
while(IFS1bits.INT1IF) //等待中斷
{
IFS1bits.INT1IF=0;
i2c_interrupt_init(); //重新初始化中斷,以便清除8583芯片內(nèi)中斷標(biāo)志位
i2c_read(); //讀取時(shí)間
hex2bcd(); /結(jié)果轉(zhuǎn)換成BCD碼
lcd_display(); /送LCD顯示
}
}
}