ATmega32驱动16x2 LCD显示DS1307小时数据无输出问题咨询
问题原因及修复方案
1 小时数据无法在LCD显示的原因
- 野指针触发程序异常:
rtc_getTime函数内定义的unsigned char *data未分配有效内存空间,直接解引用赋值属于非法内存访问,会触发不可预期的运行错误,大概率导致程序跑飞,后续LCD初始化、显示相关代码根本无法正常执行。 - DS1307数据格式处理错误:DS1307的时间寄存器采用BCD编码存储数据,你写入的
0x22是单字节BCD值,代表十进制22,并非两个独立的字符数据。你将返回的指针作为长度为2的数组访问hours[0]、hours[1],读取到的都是无效随机数据。 - LCD接口调用逻辑错误:
lcd_print函数要求传入以\0结尾的字符串指针,你直接把hours[0]这类数值作为指针传入,会让函数访问非法内存地址,无法输出有效内容;且数值未转换为LCD可识别的ASCII字符,即使传参正确也无法显示对应数字。
2 代码修改方案
步骤1:修改rtc_getTime函数及声明,规避指针问题
首先修改函数声明,将返回值从指针改为单字节数值:
// 把原来的声明替换为下面这行 unsigned char rtc_getTime(unsigned char deviceRegister);
再修改函数实现,直接返回读取到的寄存器值:
unsigned char rtc_getTime(unsigned char deviceRegister){ unsigned char data; i2c_start(); i2c_write(0xD0); i2c_write(deviceRegister); i2c_stop(); i2c_start(); i2c_write(0xD1); data = i2c_read(0); i2c_stop(); return data; }
步骤2:修改main函数,完成BCD转ASCII并正确调用显示接口
将读取到的BCD编码小时值拆分为十位、个位,转换为ASCII字符后输出到LCD:
int main(void) { unsigned char hours_bcd, hour_tens, hour_units; rtc_init(); rtc_setTime(0x02, 0x22); // 写入BCD编码的22点 hours_bcd = rtc_getTime(0x02); // BCD码转ASCII字符 hour_tens = ((hours_bcd >> 4) & 0x0F) + '0'; hour_units = (hours_bcd & 0x0F) + '0'; lcd_init(); lcd_gotoxy(1,1); lcdData(hour_tens); lcd_gotoxy(2,1); lcdData(hour_units); while (1); return 0; }
如果需要使用lcd_print输出,可以提前把小时值拼接为字符串:
int main(void) { unsigned char hours_bcd; char hour_str[3] = {0}; // 预留两位字符+字符串结束符 rtc_init(); rtc_setTime(0x02, 0x22); hours_bcd = rtc_getTime(0x02); hour_str[0] = ((hours_bcd >> 4) & 0x0F) + '0'; hour_str[1] = (hours_bcd & 0x0F) + '0'; lcd_init(); lcd_gotoxy(1,1); lcd_print(hour_str); while (1); return 0; }
内容的提问来源于stack exchange,提问作者Mahmoud Abdel-Rahman
相关产品推荐
相关产品推荐

