linux 下 i2c 的驱动 以及 与时钟芯片 pcf8563之间的通信(二)
2012/7/10
linux下i2c驱动与通信(二)
by:韩大卫 @吉林师范大学
在i2c-test的基础上, 使用i2c与Pcf8563通信,通过发送和接收数据,对rtc芯片进行set 和get操作。
既然是操作时间,可以使用struct rtc_time, 定义如下:
struct rtc_time {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
}
在pcf8563_get_datetime() 中:
struct i2c_msg msgs[] = {
{ client->addr, 0, 1, buf }, /* setup read ptr */
{ client->addr, I2C_M_RD, 13, buf }, /* read status + date */
};
定义了两个msg, 在i2c-octeon 中分别进入了
ret = octeon_i2c_simple_write()
ret = octeon_i2c_read()
进入simple_write()作用是将第一个buf 即offset 写入寄存器,这样在read函数即可直接读此寄存器。
2012.7.11 .14:50
出现这样一个问题:
root@juson:/han# ./i2c-test
strlen(buf) = 1
buf[0] = 8
root@juson:/han# ./i2c-test -r
strlen(buf) = 1
buf[0] = 8
root@juson:/han# ./i2c-test -l
2012年 07月 11日 星期三 21:49:41
root@juson:/han# ./i2c-test
strlen(buf) = 13
buf[0] = 8
buf[1] = 40
buf[2] = 43
buf[3] = 49
buf[4] = 21
buf[5] = 11
buf[6] = 3
buf[7] = 7
buf[8] = 12
buf[9] = a0
buf[10] = 84
buf[11] = b2
buf[12] = b5
有少两情况下会出现strlen(buf) = 13
过一会:
root@juson:/han# ./i2c-test
strlen(buf) = 13
buf[0] = 8
buf[1] = 40
buf[2] = 54
buf[3] = 53
buf[4] = 21
buf[5] = 11
buf[6] = 3
buf[7] = 7
buf[8] = 12
buf[9] = a0
buf[10] = 84
buf[11] = b2
buf[12] = b5
root@juson:/han# ./i2c-test
strlen(buf) = 13
buf[0] = 8
buf[1] = 40
buf[2] = 55
buf[3] = 53
buf[4] = 21
buf[5] = 11
buf[6] = 3
buf[7] = 7
buf[8] = 12
buf[9] = a0
buf[10] = 84
buf[11] = b2
buf[12] = b5
这次是全部是root@juson:/han# ./i2c-test
strlen(buf) =13 的情况。
代码中:
for(i = 0; i< strlen(buf); i++)
printf("buf[%d] = %x\n",i,buf[i]);
本意是想看经过read_data(addr, offset, buf) 后, buf中成员有多少被赋值了,但忘记了一个地方:
strlen(buf)
这个函数是遇到buf中的0,或者'\0' 就截止的,恰好 第二个寄存器01h control_status 的值有时候恰好为0x0,或者0x40,这样,当为0x0时候strlen(buf) 就为1了。
01h control_status_2 0 0 STOP 0 TESTC 0 0 0
改为 for(i = 0; i< 13; i++)
printf("buf[%d] = %x\n",i,buf[i]);
可以看出,strlen(buf) = 13
buf[0] = 8
buf[1] = 40
buf[2] = 43
buf[3] = 15
buf[4] = 22
buf[5] = 11
buf[6] = 3
buf[7] = 7
buf[8] = 12
buf[9] = a0
buf[10] = 84
buf[11] = b2
buf[12] = b5
另一种情况:
strlen(buf) = 1
buf[0] = 8
buf[1] = 0
buf[2] = 39
buf[3] = 15
buf[4] = 22
buf[5] = 11
buf[6] = 3
buf[7] = 7
buf[8] = 12
buf[9] = a0
buf[10] = 84
buf[11] = b2
buf[12] = b5
这时候strlen就出现了让人迷惑的显示!
15:50 。出现了段错误:
这条语句:
tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
52 /*
53 tm->tm_min = buf[PCF8563_REG_MN] & 0x7F;
54 tm->tm_hour = buf[PCF8563_REG_HR] & 0x3F; // rtc hr 0-23
55 tm->tm_mday = buf[PCF8563_REG_DM] & 0x3F;
tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
检查了struct rtc_time{
成员都是对的。怎么会段错误。
肯定的指针的问题。
struct rtc_time *tm;
tm->tm_min = buf[PCF8563_REG_MN] & 0x7F;
tm->tm_hour = buf[PCF8563_REG_HR] & 0x3F; // rtc hr 0-23
tm->tm_mday = buf[PCF8563_REG_DM] & 0x3F;
平时运行的时候都没有出现问题,但本身是有问题的。
错误原因: *tm 本身是野指针 !
定义了这个指针后:要用malloc 对tm 进行分配内存。
struct rtc_time *tm = (struct rtc_time*)malloc(sizeof(struct rtc_time));
总结: 使用指针时候,一定要谨慎! 一定要先malloc, 再对其内容操作!
17:39
另一个问题:
unsigned char data;
data 最大只能存255, 256就是0了。
那么
write_data(0x51,0x08,data) 的时候,
年份不能直接传给data,否则会溢出。
就是2012:07:11 时候,如果将2012直接赋值给data,那么会产生溢出,data不会是原来的值。
2012 的bin是: 11111011100
unsigned char data 之能保存8bit,
1101 1100
十进制是220。
怎么办:
先参考pcf8563_set_datetime。中的代码:
unsigned char buf[9];
/* hours, minutes and seconds */
buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
/* month, 1 - 12 */
buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
/* year and century */
buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
%100, 就可以把最后的8bit取得。
if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
这样把PCF8563_REG_MO的 PCF8563_MO_C bit 决定是否置位。
2012.7.12
一个新的小问题:
if(*(ptr+2) == ':'){
tm->tm_hour = atoi(ptr);
tm->tm_min = atoi(ptr + 3);
tm->tm_sec = atoi(ptr + 6);
}
else if(*(ptr+4) == ':'){
tm->tm_year = atoi(ptr);
tm->tm_mon = atoi(ptr + 5);
tm->tm_mday = atoi(ptr + 8);
if(*(ptr+10) == '-'){
tm->tm_hour = atoi(ptr + 11);
tm->tm_min = atoi(ptr + 14);
tm->tm_sec = atoi(ptr + 17);
}
}
这种算法,如果遇到 2012:12:12 还可以,因为每个bit 都可以对应上,
但是2012:1:1 , 2012:1.12 这种情况就不可以了。
15:29, 在这一次人品爆发下,解决了这个问题,并做了简化,
if( *(ptr+4) == '.'){
data[i++] = atoi(ptr);
while( *ptr ){

本文详细探讨了在Linux环境下,如何使用I2C驱动程序与pcf8563时钟芯片进行通信。通过C语言编程,实现了设备文件的操作,包括初始化、读写数据等关键步骤,为嵌入式系统中的时间管理提供了实用方案。
最低0.47元/天 解锁文章
262

被折叠的 条评论
为什么被折叠?



