锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

avr MEGA16单片机控制DS1302时钟芯片1602液晶显示

时间:2024-05-05 20:37:09

/*
程序名(program name) : 时钟芯片控制程序;
概述 : 基于本程序的 是本人自主研发的YF-A1 16单片机芯片开发板,信号 辅助硬件工具有一部8通道的24兆赫兹的 和一部万用表,通俗的讲,此程序就 是开发板的操作系统,以MEGA16A为中央控制芯片,来控制DS1302时钟芯片,使其时间数据 显示在1602液晶屏上; 我用业余时间大概写了三天左右....得以完善,这次我写的比较顺利,错误只有两点, 一是将写好的程序下载入芯片后,时间不走,错误在于写错了时序,用逻辑分析仪捕捉信号 后,修正,KO! 二是时间可以走,但是跑秒区并非从0走到59,问题在于显示时,直接显示 BCD码,并未将BCD码转换为十进制数,修正后OK! 此程序还用到了定时器模块,定时每100毫秒读一次时间数据,并显示在液晶屏上;

心得: 此次又突破了以往的程序量,这是我写的目前最大的一个程序,由于AVR芯片IO口 控制比较复杂,所以程序语句比较多,但是此程序还有精简的空间,IO口的初始化很重 要!

finish time: 2014年3月7日13:16:14 作者: 肖邦; QQ: 14-545-07665 ; TEL: SORRY 保密; 地址: 新疆昌吉回族自治州昌吉市; 梦想: 将 托尼*斯塔克成为现实;
*/

#include #include //此头文件用于中断服务,本程序中可以省略;
typedef unsigned char uint8; typedef unsigned int uint16;
void init_io(void) //====初始化所有io口; { A=0XFF; PORTA=0XFF;
DDRB=0XFF; PORTB=0X00;
DDRC=0XFF; PORTC=0X00;
DDRD=0XFF; PORTD=0X00; }
//================IO口的位操作==================
void rs(uint8 a) //指令/数据位/ ===========DS1302时钟位; { if(a) { PORTB|=1<<3; }
else { PORTB&=~(1<<3); } }
void rw(uint8 a) //读/写位/ ================DS1302数据位; { if(a) { PORTB|=1<<4; }
else { PORTB&=~(1<<4); } }
void e(uint8 a) //1602传输时能位; { if(a) { PORTB|=1<<5; }
else { PORTB&=~(1<<5); } }

void ds(uint8 a) //=========================DS1302传输使能位; { if(a) { PORTC|=1<<4; }
else { PORTC&=~(1<<4); } }

//==============================================

/*/====================================================== 模块名: 1602 液晶屏函数 功能: 负责将视觉需要的数据显示在屏幕上; *///===================================================== void pa7(uint8 a) //繁忙检测位================= { if(a) { DDRA|=0X80; PORTA|=0X80 ;} //输出高电平状态; else { DDRA&=~(0X80); PORTA|=0X80; }//输入内部有上拉 ; }
void busy(void) //繁忙检测函数 { pa7(0); // PA7引脚输入状态内部有上拉; do { e(0); rs(0); rw(1); e(1); //注意!此处和读写数据指令不同,要置1传输使能位,再读取,读取完成后再清零此位; }
while(PINA&0X80);//读取PA7引脚是否是0;如果是0,表示液晶屏处于空闲状态,可以进行操作; e(0);
pa7(1); //PA7引脚输出状态,输出1; }
void pa(uint8 a) //====向PA口装载数据; {
PORTA=a;
} void lcd_dat(uint8 dat)//=========写数据============== { busy(); //繁忙检测; rs(1); //数据; rw(0); //写入; e(1); //传输开始; pa(dat); //装载数据; e(0) ; //传输结束; }
void lcd_cmd(uint8 cmd) //=============写指令============= { busy(); //繁忙检测; rs(0); //指令; rw(0); //写入; e(1); //传输开始; pa(cmd); //装载数据; e(0); //传输结束; }
void init_lcd() //初始化液晶屏指令; { lcd_cmd(0x3c); //显示数据,8位数据, 两行,5X10显示; lcd_cmd(0x0c); //整屏显示光标不闪,字符不闪. lcd_cmd(0x06); //写入一个数据时地址加一,整屏不移动; lcd_cmd(0x01); //清屏指令;
}
void play(uint8 add,uint8 dat)//=======最终显示函数=================== { lcd_cmd(add); lcd_dat(dat);
}
void delay1(uint8 j,uint8 i)//====可编程延时函数======== { uint16 a=0,s=10000; s=s*j;
while(i--) { for(a=0;a }

void buzz(void) // ============= {
PORTC|=0X80; delay1(3,4); PORTC&=~(0X80);
}
//==========================================================



//==================DS1302模块===========
void reset_1302() { ds(0); rs(0); rw(0);
} void delay2(void) //用于DS1302小延时函数; { uint8 j=0; for(j=0;j<200;j++);

}
void ds_write(uint8 dat) //DS1302写数据函数; { uint8 j=0;
for(j=0;j<8;j++) { rw(dat&0x01); rs(0); rs(1); dat>>=1; } }
uint8 ds_read(void) // DS1302读取函数; { uint8 j=0,temp=0;
DDRB&=~(1<<4); //rw引脚输入状态; PORTB|=1<<4; //内部有上拉电阻; rs(0);

for(j=0;j<8;j++) { temp>>=1;

if((PINB&0X10)==0X10)//如果PB4口读到1; { temp|=0x80;//装载数据; } rs(1); //下降沿有效; delay2(); //时钟脉宽延时; rs(0); } DDRB|=1<<4; // rw引脚输出状态; PORTB|=1<<4; //rw引脚输出1; rs(0); rw(0);
return (temp);

}
void w_1302(uint8 addr,uint8 dat) //写一个地址,写一个数据; { ds_write(addr); ds_write(dat);
}

void ds_wp(uint8 j) //j==1:不能够写入数据,j==0:可以写入数据; { reset_1302(); //初始化时钟,数据,片选线; ds(1); w_1302(0x8e,j?0x80:0); //三目运算; ds(0); }

void set_time(uint8 * dat) //设置时间; { uint8 r=0 ,t=0, ad=0x80; for(r=0;r<7;r++) //BCD码的转换. { t=dat[r]%10; dat[r]=dat[r]/10; dat[r]=(dat[r]*16)+t; } ds_wp(0);//可以写入数据; for(r=0;r<7;r++) { reset_1302(); //初始化1302; ds(1); //传输使能开; ds_write(ad); //写入"写"操作地址; ds_write(dat[r]);//写入时间数据; ds(0); ad+=2;//地址加2; } ds_wp(1);//禁止写入数据;
}
void read_time(uint8 * dat) { uint8 j=0,addr=0x81 ;
for(j=0;j<7;j++) { reset_1302(); ds(1); //传输使能开; ds_write(addr); //发送读取地址; dat[j]=ds_read(); //接收读到的数据; ds(0); //传输使能关;
addr+=2; //读取地址加2; }
}
void timer0(void) //定时器模块函数; {
TCNT0=22; //每5毫秒溢出一次; TCCR0=0X04; //256分频;

}

int main(void) { uint8 j=0; uint8 sj[]={20,23,13,7,3,5,14}; init_io(); //初始化所有io口; init_lcd(); //初始化1602液晶屏;
play(0x82,'2'); delay1(3,2);
play(0x83,'0'); delay1(3,2); play(0x86,'-'); delay1(3,2);
play(0x89,'-'); delay1(3,2);
play(0x8d,'('); delay1(3,2);
play(0x8f,')'); delay1(3,2);
play(0xc4,':'); delay1(3,2);
play(0xc7,':'); delay1(3,2); buzz(); //蜂鸣器叫; delay1(3,2);
set_time(sj); //设置时间; timer0(); //运行定时器;




while(1) { if(TIFR&0X01) //定时器溢出了; { j++; TCNT0=22; TIFR|=0X01;//溢出位置一清零;
}
if(j==20) { j=0;
read_time(sj); play(0xc9,sj[0]%16+'0'); //秒个位; play(0xc8,sj[0]/16+'0'); //秒十位;
play(0xc6,sj[1]%16+'0'); //分个位; play(0xc5,sj[1]/16+'0'); //分十位;
play(0xc3,sj[2]%16+'0'); //时个位; play(0xc2,sj[2]/16+'0'); //时十位;
play(0x8b,sj[3]%16+'0'); //号个位; play(0x8a,sj[3]/16+'0'); //号十位;
play(0x88,sj[4]%16+'0'); //月个位; play(0x87,sj[4]/16+'0'); //月十位;

play(0x8e,sj[5]+'0'); //星期;

play(0x85,sj[6]%16+'0'); //秒个位; play(0x84,sj[6]/16+'0'); //秒十位;


}


}





}
-电子元器件采购网(www.ruidan.com)是本土元器件目录分销商,采用“小批量、现货、样品”销售模式,致力于满足客户多型号、高质量、快速交付的采购需求。 自建高效智能仓储,拥有自营库存超过50,000种,提供一站式正品现货采购、个性化解决方案、选型替代等多元化服务。
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章