📄 rtc.lst
字号:
01F5 E04B LDI R20,0xB
(0093) break;
01F6 C007 RJMP 0x01FE
(0094) case 0xE7:
(0095) keycode=0xC;
01F7 E04C LDI R20,0xC
(0096) break;
01F8 C005 RJMP 0x01FE
(0097) case 0xD7:
(0098) keycode=0xD;
01F9 E04D LDI R20,0xD
(0099) break;
01FA C003 RJMP 0x01FE
(0100) case 0xB7:
(0101) keycode=0xE;
01FB E04E LDI R20,0xE
(0102) break;
01FC C001 RJMP 0x01FE
(0103) case 0x77:
(0104) keycode=0xF;
01FD E04F LDI R20,0xF
(0105) break;
(0106) }
(0107) }
(0108) return keycode; //返回经过翻译的键码
01FE 2F04 MOV R16,R20
01FF 940E070A CALL pop_gset3
0201 9508 RET
FILE: C:\icc\examples.avr\AVR_PQ1A_DEMO\17_RTC\RTC.C
(0001) /*******************************************
(0002) 文件:RTC.C
(0003) 环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10
(0004) 硬件:ATMEGA16芯片
(0005) 日期:2006年12月10日
(0006) 功能:驱动开发板上的DS1302时钟芯片
(0007) 备注:参考《AVR系列单片机C语言编程与应用实例》(清华大学出版社)
(0008) /******************************************/
(0009) #include <iom16v.h> //包含型号头文件
(0010) #include <macros.h> //包含"位"操作头文件
(0011) #include <stdio.h> //标准输入输出头文件
(0012) #include <AVR_PQ1A.h> //包含自定义常量头文件
(0013) #include "YJ1602.C" //包含1602液晶函数文件
(0014) #include "MKEY.C" //包含矩阵键盘函数文件
(0015)
(0016) /*******************************************
(0017) 函数名称: DS1302_init
(0018) 功 能: 初始化DS1302的数据接口
(0019) 参 数: 无
(0020) 返回值 : 无
(0021) /********************************************/
(0022) void DS1302_portinit(void)
(0023) {
(0024) DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出
_DS1302_portinit:
0202 B387 IN R24,P17
0203 6A80 ORI R24,0xA0
0204 BB87 OUT P17,R24
(0025) }
0205 9508 RET
_DS1302_writeB:
i --> R20
byte --> R22
0206 940E06FF CALL push_gset2
0208 2F60 MOV R22,R16
(0026) /*******************************************
(0027) 函数名称: DS1302_writeB
(0028) 功 能: 向DS1302写入一个字节数据(没有RST操作)
(0029) 参 数: byte--要写入的数据
(0030) 返回值 : 无
(0031) /********************************************/
(0032) void DS1302_writeB(uchar byte)
(0033) {
(0034) uchar i;
(0035) for(i=0;i<8;i++) //8位数据计数
0209 2744 CLR R20
020A C00C RJMP 0x0217
(0036) {
(0037) PORTB&=~BIT(RTC_CLK); //拉低时钟端
020B 98C7 CBI P18,7
(0038) if(byte&0x01) //当前位是否是1
020C FF60 SBRS R22,0
020D C002 RJMP 0x0210
(0039) {
(0040) PORTB|=BIT(RTC_DATA); //当前位是1,拉高数据端
020E 9AC5 SBI P18,5
(0041) }
020F C001 RJMP 0x0211
(0042) else
(0043) {
(0044) PORTB&=~BIT(RTC_DATA); //当前位是0,拉低数据端
0210 98C5 CBI P18,5
(0045) }
(0046) Delayus(10); //调整时钟和脉冲宽度
0211 E00A LDI R16,0xA
0212 E010 LDI R17,0
0213 DE67 RCALL _Delayus
(0047) PORTB|=BIT(RTC_CLK); //时钟上升沿(DS1302采样数据)
0214 9AC7 SBI P18,7
(0048) byte>>=1; //数据右移1位,为送出新数据位做准备
0215 9566 LSR R22
0216 9543 INC R20
0217 3048 CPI R20,0x8
0218 F390 BCS 0x020B
(0049) }
(0050) }
0219 940E0707 CALL pop_gset2
021B 9508 RET
_DS1302_readB:
i --> R20
byte --> R22
021C 940E06FF CALL push_gset2
(0051) /*******************************************
(0052) 函数名称: DS1302_readB
(0053) 功 能: 从DS1302读出一个字节数据(没有RST操作)
(0054) 参 数: 无
(0055) 返回值 : byte--读出的数据
(0056) /********************************************/
(0057) uchar DS1302_readB(void)
(0058) {
(0059) uchar i,byte=0;
021E 2766 CLR R22
(0060) DDRB&=~BIT(RTC_DATA); //将数据端口设置为输入
021F 98BD CBI P17,5
(0061) PORTB&=~BIT(RTC_DATA); //无上拉电阻
0220 98C5 CBI P18,5
(0062) for(i=0;i<8;i++) //8位数据计数
0221 2744 CLR R20
0222 C00F RJMP 0x0232
(0063) {
(0064) byte>>=1; //保存读入的数据位
0223 9566 LSR R22
(0065) PORTB|=BIT(RTC_CLK); //时钟上升沿
0224 9AC7 SBI P18,7
(0066) Delayus(10); //延时,调整时钟脉冲宽度
0225 E00A LDI R16,0xA
0226 E010 LDI R17,0
0227 DE53 RCALL _Delayus
(0067) PORTB&=~BIT(RTC_CLK); //时钟下降沿,DS1302输出数据位
0228 98C7 CBI P18,7
(0068) Delayus(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)
0229 E00A LDI R16,0xA
022A E010 LDI R17,0
022B DE4F RCALL _Delayus
(0069) if(PINB&BIT(RTC_DATA)) //当前位是否是高电平
022C 9BB5 SBIS P16,5
022D C002 RJMP 0x0230
(0070) {
(0071) byte|=BIT(PB7); //是高电平就将返回数据的当前位置1
022E 6860 ORI R22,0x80
(0072) }
022F C001 RJMP 0x0231
(0073) else
(0074) {
(0075) byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0
0230 776F ANDI R22,0x7F
0231 9543 INC R20
0232 3048 CPI R20,0x8
0233 F378 BCS 0x0223
(0076) }
(0077) }
(0078) DDRB|=BIT(RTC_DATA); //最后将数据端口设置为输出
0234 9ABD SBI P17,5
(0079) return byte; //返回读出的数据
0235 2F06 MOV R16,R22
0236 940E0707 CALL pop_gset2
0238 9508 RET
_DS1302_writeD:
data --> R20
addr --> R22
0239 940E06FF CALL push_gset2
023B 2F42 MOV R20,R18
023C 2F60 MOV R22,R16
(0080) }
(0081) /*******************************************
(0082) 函数名称: DS1302_writeD
(0083) 功 能: 向DS1302的某个地址写入一个字节数据
(0084) 参 数: addr--地址值(寄存器或RAM)
(0085) data--要写入的地址
(0086) 返回值 : 无
(0087) /********************************************/
(0088) void DS1302_writeD(uchar addr,uchar data)
(0089) {
(0090) PORTC&=~BIT(RTC_CS); //拉低片选端
023D 98AF CBI P15,7
(0091) PORTB&=~BIT(RTC_CLK); //拉低时钟端
023E 98C7 CBI P18,7
(0092) Delayus(10);
023F E00A LDI R16,0xA
0240 E010 LDI R17,0
0241 DE39 RCALL _Delayus
(0093) PORTC|=BIT(RTC_CS); //拉高片选端
0242 9AAF SBI P15,7
(0094) Delayus(10); //调整片选脉冲
0243 E00A LDI R16,0xA
0244 E010 LDI R17,0
0245 DE35 RCALL _Delayus
(0095) DS1302_writeB(addr); //写入操作命令(地址)
0246 2F06 MOV R16,R22
0247 DFBE RCALL _DS1302_writeB
(0096) Delayus(10);
0248 E00A LDI R16,0xA
0249 E010 LDI R17,0
024A DE30 RCALL _Delayus
(0097) PORTB&=~BIT(RTC_CLK); //拉低时钟端
024B 98C7 CBI P18,7
(0098) Delayus(10);
024C E00A LDI R16,0xA
024D E010 LDI R17,0
024E DE2C RCALL _Delayus
(0099) DS1302_writeB(data); //写入数据
024F 2F04 MOV R16,R20
0250 DFB5 RCALL _DS1302_writeB
(0100) PORTB&=~BIT(RTC_CLK); //拉低时钟端
0251 98C7 CBI P18,7
(0101) Delayus(10); //调整片选脉冲
0252 E00A LDI R16,0xA
0253 E010 LDI R17,0
0254 DE26 RCALL _Delayus
(0102) PORTC&=~BIT(RTC_CS); //拉低片选端
0255 98AF CBI P15,7
(0103) }
0256 940E0707 CALL pop_gset2
0258 9508 RET
_DS1302_readD:
data --> R20
addr --> R20
0259 940E06E8 CALL push_gset1
025B 2F40 MOV R20,R16
(0104) /*******************************************
(0105) 函数名称: DS1302_readD
(0106) 功 能: 从DS1302的某个地址读出一个字节数据
(0107) 参 数: addr--地址值(寄存器或RAM)
(0108) 返回值 : data--读出的数据
(0109) /********************************************/
(0110) uchar DS1302_readD(uchar addr)
(0111) {
(0112) uchar data;
(0113) PORTC&=~BIT(RTC_CS); //拉低片选端
025C 98AF CBI P15,7
(0114) PORTB&=~BIT(RTC_CLK); //拉低时钟端
025D 98C7 CBI P18,7
(0115) Delayus(10);
025E E00A LDI R16,0xA
025F E010 LDI R17,0
0260 DE1A RCALL _Delayus
(0116) PORTC|=BIT(RTC_CS); //拉高片选端
0261 9AAF SBI P15,7
(0117) Delayus(10); //调整片选脉冲
0262 E00A LDI R16,0xA
0263 E010 LDI R17,0
0264 DE16 RCALL _Delayus
(0118) DS1302_writeB(addr); //写入操作命令(地址)
0265 2F04 MOV R16,R20
0266 DF9F RCALL _DS1302_writeB
(0119) Delayus(10);
0267 E00A LDI R16,0xA
0268 E010 LDI R17,0
0269 DE11 RCALL _Delayus
(0120) data=DS1302_readB(); //读出数据
026A DFB1 RCALL _DS1302_readB
026B 2F40 MOV R20,R16
(0121) Delayus(10);
026C E00A LDI R16,0xA
026D E010 LDI R17,0
026E DE0C RCALL _Delayus
(0122) PORTB&=~BIT(RTC_CLK); //拉低时钟端
026F 98C7 CBI P18,7
(0123) PORTC&=~BIT(RTC_CS); //拉低片选端
0270 98AF CBI P15,7
(0124) return data; //返回读出的数据
0271 2F04 MOV R16,R20
0272 940E06EB CALL pop_gset1
0274 9508 RET
_DS1302_setT:
addr --> R20
i --> R22
ptTimeD --> R10
0275 940E0703 CALL push_gset3
0277 0158 MOVW R10,R16
(0125) }
(0126) /*******************************************
(0127) 函数名称: DS1302_setT
(0128) 功 能: 设置DS1302的时间
(0129) 参 数: ptTimeD--设置时间数组指针
(0130) 返回值 : 无
(0131) /********************************************/
(0132) void DS1302_setT(uchar ptTimeD[])
(0133) {
(0134) uchar i;
(0135) uchar addr = 0x80; //写入地址从秒寄存器开始
0278 E840 LDI R20,0x80
(0136) DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作
0279 2722 CLR R18
027A E80E LDI R16,0x8E
027B DFBD RCALL _DS1302_writeD
(0137) Delayms(5);
027C E005 LDI R16,5
027D E010 LDI R17,0
027E DE14 RCALL _Delayms
(0138) for(i=0;i<7;i++)
027F 2766 CLR R22
0280 C00C RJMP 0x028D
(0139) {
(0140) DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 时 日 月 星期 年
0281 2FE6 MOV R30,R22
0282 27FF CLR R31
0283 0DEA ADD R30,R10
0284 1DFB ADC R31,R11
0285 8120 LDD R18,0+Z
0286 2F04 MOV R16,R20
0287 DFB1 RCALL _DS1302_writeD
(0141) addr+=2;
0288 5F4E SUBI R20,0xFE
(0142) Delayms(1);
0289 E001 LDI R16,1
028A E010 LDI R17,0
028B DE07 RCALL _Delayms
028C 9563 INC R22
028D 3067 CPI R22,7
028E F390 BCS 0x0281
(0143) }
(0144) DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作
028F E820 LDI R18,0x80
0290 E80E LDI R16,0x8E
0291 DFA7 RCALL _DS1302_writeD
(0145) }
0292 940E070A CALL pop_gset3
0294 9508 RET
_DS1302_getT:
addr --> R20
i --> R22
time --> R10
0295 940E0703 CALL push_gset3
0297 0158 MOVW R10,R16
(0146) /*******************************************
(0147) 函数名称: DS1302_getT
(0148) 功 能: 读取DS1302的当前时间
(0149) 参 数: time[]--读取的时间数组
(0150) 返回值 : 无
(0151) /********************************************/
(0152) void DS1302_getT(uchar time[])
(0153) {
(0154) uchar i;
(0155) uchar addr = 0x80; //读取地址从秒寄存器开始
0298 E840 LDI R20,0x80
(0156) for(i=0;i<7;i++)
0299 2766 CLR R22
029A C00A RJMP 0x02A5
(0157) {
(0158) time[i]=DS1302_readD(addr|RD); // 秒 分 时 日 月 星期 年
029B 2F04 MOV R16,R20
029C 6001 ORI R16,1
029D DFBB RCALL _DS1302_readD
029E 2FE6 MOV R30,R22
029F 27FF CLR R31
02A0 0DEA ADD R30,R10
02A1 1DFB ADC R31,R11
02A2 8300 STD R16,0+Z
(0159) addr+=2;
02A3 5F4E SUBI R20,0xFE
02A4 9563 INC R22
02A5 3067 CPI R22,7
02A6 F3A0 BCS 0x029B
(0160) }
(0161) PORTB&=~BIT(RTC_CLK); //拉低时钟端(时钟端在不操作时为低)
02A7 98C7 CBI P18,7
(0162) }
02A8 940E070A CALL pop_gset3
02AA 9508 RET
_DS1302_check:
exist --> R20
02AB 940E06E8 CALL push_gset1
(0163) /*******************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -