linux下i2c驱动以及与pcf8563通信(二)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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 ){
if( *ptr == '.' ){
ptr++;
data[i++] = atoi(ptr);
}
else ptr++;
}
这样把2012.1.12
2012.2.3
2012.12.13
2012.12.1
这类情况搞定了。

封装成函数:
int time_year_begin(char* ptr,struct rtc_time* tm){
int i = 0;
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':'){
ptr++;
data[i++] = atoi(ptr);
}
ptr++;
if( *ptr == '-'){
ptr++;
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':' ){
ptr++;
data[i++] = atoi(ptr);
}
else ptr++;
}
break;
}
}
tm->tm_year = data[0];
tm->tm_mon = data[1];
tm->tm_mday = data[2];
tm->tm_hour = data[3];
tm->tm_min = data[4];
tm->tm_sec = data[5];
printf("%d年%d月%d日",tm->tm_year,tm->tm_mon,tm->tm_mday); printf("%02d:%02d:%02d\n",tm->tm_hour,tm->tm_min,tm->tm_sec); return 0;
}
int time_hour_begin(char *ptr,struct rtc_time* tm){
int i = 0;
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':'){
ptr++;
data[i++] = atoi(ptr);
}
else
ptr++;
}
tm->tm_hour = data[0];
tm->tm_min = data[1];
tm->tm_sec = data[2];
printf("%02d:%02d:%02d\n",tm->tm_hour,tm->tm_min,tm->tm_sec); return 0;
}
在main.c 中
int c = atoi(ptr);
if( c /1000 )
time_year_begin(ptr,tm);
else
time_hour_begin(ptr,tm);
18:18 出现了一个问题:
./i2c-test -s 18.18.30
18:18:30
root@juson:/han# hwclock -r
Tue Nov 30 18:18:34 1999 -0.232654 seconds
如果单独设置hour:min:sec
那么year,mon,mdays 的值就是0 了。

这样
for(offset = PCF8563_REG_SC; offset <= PCF8563_REG_YR ; offset++ ){
write_data(addr,offset,buf[offset]);
}
时候,会对rtc原来的时候进行覆盖。

那么就对
for(offset = PCF8563_REG_SC; offset <= PCF8563_REG_YR ; offset++ ){
write_data(addr,offset,buf[offset]);
}
这个地方进行修改。

另一个问题:
date -s 1982.1.1-12:1
Fri Jan 1 12:01:00 UTC 1982
root@juson:/han# hwclock -w
root@juson:/han# ./i2c-test
1982年01月:01日Fir 12:01:05
./i2c-test -s 2012.12.20-12.4.9
2012年12月20日12:04:09
root@juson:/han# hwclock -r
Thu Dec 20 12:04:14 2012 -0.238584 seconds
使用./i2c-test -s 对时间进行修改后,无法用./i2c-test 读出星期。

这是因为在set_data 时候没有对wday 寄存器进行相应的写操作。

怎么写如相应的星期信息,有两个思路:
1,根据设置的TIME 值计算出当前星期信息,再赋值给wday寄存器。

这样使用一次写函数,一个读函数即可显示出rtc-time。

2,完成TIME 的写操作后,再读出wday 寄存器的值,显示在rtc_time_list()函数中。

这种做法是先使用一次写函数,让处理器计算出wday的值,再使用一次读函数读出wday寄存器,再使用一次读函数显示出完整的rtc-time。

显然第一种方法值得研究。

实现一个根据提供的年,月,日信息来获得当前星期的函数get_week_data(int year,int mon,int day)在网上找到一个代码,
int get_week_data(int y,int m,int d){
unsigned int w, c;
if (m <= 2){
m |= 4;//1月2月同5月六月表
y--;
}
c = y / 100;
c &= 0x03;//百年%4
y %= 100;
w = ((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;//(星期=百年%4*5+年+年/4+(1 3*月+8)/5+日)%7
return w;//返回星期
}
测试后还可以,就是2012.2.30 时候,显示6,但实际上没有这个日期。

类是bug还有:2012.13.30
2012.12.1-40:12:12
这类时间越界的的问题。

static const unsigned char rtc_days_in_month[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static inline int is_leap_year(unsigned int year){
return (!(year % 4) && (year % 100)) || !(year % 400);
}
int rtc_month_days(unsigned int month, unsigned int year){
return rtc_days_in_month[month - 1] + (is_leap_year(year) && month == 1);
}
int rtc_valid_tm(struct rtc_time *tm)
{
if (tm->tm_year < 1970
|| ((unsigned)tm->tm_mon) > 12
|| tm->tm_mday < 0
|| tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year)
|| ((unsigned)tm->tm_hour) >= 24
|| ((unsigned)tm->tm_min) >= 60
|| ((unsigned)tm->tm_sec) >= 60)
return -EINVAL;
return 0;
}
加上个判断函数后,便可以判断出,超出时间越界的问题。

测试时候又出现了一问题:
i2c-test -s 123jlk12j3
123:00:00
这是由于:
if( c /1000 )
time_year_begin(ptr,tm);
else
time_hour_begin(ptr,tm);
没有对-s 后面的参数对强制判断。

在这两个函数中加上判断条件,
int time_year_begin(char* ptr,struct rtc_time* tm){
if( !(*(ptr+4) == "." || *(ptr+4) == ":" ))
printf("TIME Format error !\n");
exit(-1);
}
...
}
之所以没有在i2c_rtc_data()中直接判断,是因为可能有:2012.12.1
12.1.1
这样*(ptr+4) 都是等于. 不能判断出是否进入是2012.1.1. 还是13:12:30 两者的区别。

现在还剩一个问题了
就是设置2012.1.1 时,怎么不把hour,min,sec 的值覆盖掉。

定义了一个hour_flags;
int set_hour_flags = 0;
unsigned char buf[8] = {0};
int data[10] = {0};
// get year
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':'){
ptr++;
//get mon and mday
data[i++] = atoi(ptr);
}
ptr++;
if( *ptr == '-'){
set_hour_flags = 1;
ptr++;
//get hour
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':' ){
ptr++;
//get min and sec
data[i++] = atoi(ptr);
}
else ptr++;
}
break;
}
}
tm->tm_year = data[0];
tm->tm_mon = data[1];
tm->tm_mday = data[2];
tm->tm_hour = data[3];
tm->tm_min = data[4];
tm->tm_sec = data[5];
tm->tm_wday = get_week_data(tm->tm_year,tm->tm_mon,tm->tm_mday);
if(rtc_valid_tm(tm) < 0){
printf("date/time is not valid.set time error!\n");
exit(-1);
}
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);
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon);
buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
if ( tm->tm_year/2000 )
buf[PCF8563_REG_MO] |= 0x00;
else
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
//write year-wday or year-sec
for(offset = set_hour_flags? PCF8563_REG_SC : PCF8563_REG_DM; offset <= PCF8563_RE G_YR ; offset++ ){
write_data(addr,offset,buf[offset]);
}
使用hour_flags 作为判断条件,来对offset赋值,在执行for进行write时候,从这个范围内的offset进行write。

并将
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);
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;。

这个部分从rtc_i2c_data 中分别移动到分支函数中。

至此。

这个程序就算写完了。

下面是完整的代码:
main.c
************************************************* **********************
#include "i2c.h"
#define TIMEOUT3
#define RETRY3
static int fd;
static inline int is_leap_year(unsigned int year){
return (!(year % 4) && (year % 100)) || !(year % 400);
}
int rtc_month_days(unsigned int month, unsigned int year){
return rtc_days_in_month[month - 1] + (is_leap_year(year) && month == 1); }
/*
*test year.mon.mday.wday.hour.min.sec
*/
int rtc_valid_tm(struct rtc_time *tm)
{
if(tm->tm_year < 1970
|| tm->tm_year >2069
|| ((unsigned)tm->tm_mon) > 12
|| tm->tm_mday < 0
|| tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year)
|| ((unsigned)tm->tm_hour) >= 24
|| ((unsigned)tm->tm_min) >= 60
|| ((unsigned)tm->tm_sec) >= 60)
return -EINVAL;
return 0;
}
/*
*test hour:min:sec
*/
int rtc_valid_half_tm(struct rtc_time *tm)
{
if((unsigned)tm->tm_hour >= 24 ||
(unsigned)tm->tm_min >= 60 ||
(unsigned)tm->tm_sec >= 60)
return -EINVAL;
return 0;
}
int i_open(unsigned char* dev, unsigned int timeout, unsigned int retry){
return i2c_open(dev,timeout,retry);
}
int read_data(u16 addr, u8 offset, u8 *val){
int ret;
ret = i2c_read_data(addr,offset,val);
if(ret < 0){
printf("%s error!\n",__FUNCTION__);
exit(-1);
}
return 0;
}
int write_data(u16 addr, u8 offset, u8 val){
int ret;
ret = i2c_write_data(addr,offset,val);
if(ret < 0){
printf("%s error!\n",__FUNCTION__);
exit(-1);
}
return 0;
}
int get_week_data(int y,int m,int d){
unsigned int w, c;
if (m <= 2){
m |= 4;
y--;
}
c =y/100;
c &=0x03;
y %=100;
w =((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;
return w;
}
/*
*-s YYYY.MM.DD-hh.mm.ss
*/
int time_year_begin(char* ptr,struct rtc_time* tm){
if( !(*(ptr+4) == '.' || *(ptr+4) == ':' )){
printf("TIME Format error !\n");
exit(-1);
}
u8 offset;
u16 addr = 0x51;
int i= 0;
int set_hour_flags=0;
unsigned char buf[8]={0};
int data[10]={0};
/* get year */
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':'){
ptr++;
/* get mon and mday */
data[i++] = atoi(ptr);
}
ptr++;
if( *ptr == '-'){
set_hour_flags = 1;
ptr++;
/* get hour */
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':' ){
ptr++;
/* get min and sec */
data[i++] = atoi(ptr);
}
else ptr++;
}
break;
}
}
tm->tm_year = data[0];
tm->tm_mon = data[1];
tm->tm_mday = data[2];
tm->tm_hour = data[3];
tm->tm_min = data[4];
tm->tm_sec = data[5];
tm->tm_wday=get_week_data(tm->tm_year,tm->tm_mon,tm->tm_mday);
if(rtc_valid_tm(tm) < 0){
printf("date/time is not valid.set time error!\n");
exit(-1);
}
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);
buf[PCF8563_REG_DW]=tm->tm_wday & 0x07;
buf[PCF8563_REG_MO]=bin2bcd(tm->tm_mon);
buf[PCF8563_REG_YR]=bin2bcd(tm->tm_year % 100);
if ( tm->tm_year/2000 )
buf[PCF8563_REG_MO] |= 0x00;
else
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
/* write year-wday or year-sec*/
for(offset = set_hour_flags? PCF8563_REG_SC : PCF8563_REG_DM; offset <= PCF8563_REG _YR ; offset++ ){
write_data(addr,offset,buf[offset]);
}
rtc_time_list();
return 0;
}
/*
*-s hh.mm.ss
*/
int time_hour_begin(char *ptr,struct rtc_time* tm){
if( !(*(ptr+2) == '.' || *(ptr+1) == '.' || *(ptr+2) == ':' || *(ptr+1) == ':') ){
printf("TIME Format error !\n");
exit(-1);
}
u8 offset;
u16 addr =0x51;
int i =0;
unsigned char buf[4]={0};
int data[10]={0};
/* get hour */
data[i++] = atoi(ptr);
while( *ptr ){
if( *ptr == '.' || *ptr == ':'){
ptr++;
/* get min and sec */
data[i++] = atoi(ptr);
}
else
ptr++;
}
tm->tm_hour = data[0];
tm->tm_min = data[1];
tm->tm_sec = data[2];
if(rtc_valid_half_tm(tm) < 0){
printf("date/time is not valid.set time error!\n");
exit(-1);
}
buf[PCF8563_REG_SC]=bin2bcd(tm->tm_sec);
buf[PCF8563_REG_MN]=bin2bcd(tm->tm_min);
buf[PCF8563_REG_HR] =bin2bcd(tm->tm_hour);
for(offset = PCF8563_REG_SC; offset <= PCF8563_REG_HR ; offset++ ){
write_data(addr,offset,buf[offset]);
}
rtc_time_list();
return 0;
}
int rtc_time_list(void){
u16 addr=0x51;
u8 offset=0x00;
u8 buf[13]={0};
int data[10]={0};
struct rtc_time *tm = (struct rtc_time*)malloc(sizeof(struct rtc_time));
read_data(addr, offset, buf);
tm->tm_sec=buf[PCF8563_REG_SC] & 0x7F;
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->tm_wday=buf[PCF8563_REG_DW] & 0x07;
tm->tm_mon=buf[PCF8563_REG_MO] & 0x1F;// rtc mn 1-12 -1 :tm_mon: [0-11] tm->tm_year=buf[PCF8563_REG_YR];
if(buf[PCF8563_REG_MO] & PCF8563_MO_C)
tm->tm_year+=0x1900;//MO:8bit = 1:1900 else
tm->tm_year+=0x2000;//MO:8bit = 0:2000 printf("%4x:%02x:%02x ",
tm->tm_year, tm->tm_mon, tm->tm_mday);
switch(tm->tm_wday){
case 1 :
printf("Mon ");break;
case 2 :
printf("Tus ");break;
case 3 :
printf("Wed ");break;
case 4 :
printf("Thu ");break;
case 5 :
printf("Fir ");break;
case 6 :
printf("Sat ");break;
case 7 :
printf("Sun ");break;
}
printf("%02x:%02x:%02x\n",
tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
int sys_time_list(){
struct tm* ptr;
time_t lt;
lt = time(NULL);
ptr = localtime(&lt);
printf("%4d:",ptr->tm_year + 1900);
printf("%02d:",ptr->tm_mon + 1);
printf("%02d ",ptr->tm_mday);
switch(ptr->tm_wday){
case 1 :
printf("Mon ");break;
case 2 :
printf("Tus ");break;
case 3 :
printf("Wed ");break;
case 4 :
printf("Thu ");break;
case 5 :
printf("Fir ");break;
case 6 :
printf("Sat ");break;
case 7 :
printf("Sun ");break;
}
printf("%02d:",ptr->tm_hour);
printf("%02d:",ptr->tm_min);
printf("%02d\n",ptr->tm_sec);
return 0;
}
int i2c_rtc_data(char* ptr){
struct rtc_time* tm=(struct rtc_time*)malloc(sizeof(struct rtc_time));
int c =atoi(ptr);
if( c /1000 )
time_year_begin(ptr,tm);
else
time_hour_begin(ptr,tm);
return 0;
}
int help_info(void){
printf("\nUsage: i2c-test [OPTIONS] \n");
printf("\nOr: i2c-test -s [TIME] \n\n");
printf("\nDisplay rtc-time or sys-time, or set time.\n\n");
printf("\nOptions:\n");
printf("\n\t-r\t\tshow rtc-time\n");
printf("\n\t-l\t\tshow sys-time\n");
printf("\n\t-s [TIME]\tset rtc-time:\n");
printf("\n\t-h or --help\tshow help information\n\n");
printf("\nRecognized formats for TIME:\n");
printf("\n\tYYYY.MM.DD-hh.mm[.ss]\n");
printf("\n\tYYYY.MM.DD\n");
printf("\n\thh.mm[.ss]\n");
printf("\n\thh:mm[:ss]\n");
printf("\n\t'.' can be replaced by ':',like this: YYYY:MM.DD-hh.mm:ss \n\n");
return 0;
}
int main(int argc,char* argv[]){
fd = i_open("/dev/i2c-1",TIMEOUT,RETRY);
if( fd < 0 ){
printf("i2c_open error!\n");
exit(-1);
}
switch(argc){
case 1: {
if( rtc_time_list() ){
printf("rtctime_show error!\n");
exit(-1);
}
break;
}
case 2: {
if(!strcmp(argv[1],"-l")){
if( sys_time_list() ){
printf("systime_show error!\n");
exit(-1);
}
}else if(!strcmp(argv[1],"-r")){
if( rtc_time_list() ){
printf("rtctime_show error!\n");
exit(-1);
}
}else if(!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help" ) ) {
help_info();
}else{
printf("useless operation %s ...\n Please try -h or --help for more information\n",ar gv[1]);
exit(-1);
}
break;
}
case 3: {
if(!strcmp(argv[1], "-s")){
i2c_rtc_data(argv[2]);
}
break;
}
default:
printf("command error!\nPlease input --help for more information"),exit(-1);
}
return 0;
}
***************** ****************************************************
i2c.c
******************************* **************************************
#include "i2c.h"
static int fd;
unsigned bcd2bin(unsigned char val)
{
return (val & 0x0f) + (val >> 4) * 10;
}
unsigned char bin2bcd(unsigned val)
{
return ((val / 10) << 4) + val % 10;
}
int
i2c_read_data(u16 addr, u8 offset, u8 *val)
{
int i,ret = 0;
struct i2c_rdwr_ioctl_data *data;
if ((data = (struct i2c_rdwr_ioctl_data *)malloc(sizeof(struct i2c_rdwr_ioctl_data))) == NUL L)
return -1;
data->nmsgs = 2;
if ((data->msgs = (struct i2c_msg *)malloc(data->nmsgs * sizeof(struct i2c_msg))) == NUL L) {
ret = -1;
goto errexit3;
}
if ((data->msgs[0].buf = (unsigned char *)malloc(sizeof(unsigned char))) == NULL) { ret = -1;
goto errexit2;
}
if ((data->msgs[1].buf = (unsigned char *)malloc(sizeof(unsigned char))) == NULL) { ret = -1;
goto errexit1;
}
data->msgs[0].addr = addr;
data->msgs[0].flags = 0;
data->msgs[0].len = 1;
data->msgs[0].buf[0] = offset;
data->msgs[1].addr = addr;
data->msgs[1].flags = I2C_M_RD;
data->msgs[1].len = 13;//original data is 1
data->msgs[1].buf[0] = 0;
if ((ret = __i2c_send(fd, data)) < 0)
goto errexit0;
for(i = 0 ;i < data->msgs[1].len; i++)
val[i] = data->msgs[1].buf[i];
errexit0:
free(data->msgs[1].buf);
errexit1:
free(data->msgs[0].buf);
errexit2:
free(data->msgs);
errexit3:
free(data);
return ret;
}
int
i2c_write_data(u16 addr, u8 offset, u8 val)
{
int ret = 0;
struct i2c_rdwr_ioctl_data *data;
if ((data = (struct i2c_rdwr_ioctl_data *)malloc(sizeof(struct i2c_rdwr_ioctl_data))) == NUL L)
return -1;
data->nmsgs = 1;
if ((data->msgs = (struct i2c_msg *)malloc(data->nmsgs * sizeof(struct i2c_msg))) == NUL L) {
ret = -1;
goto errexit2;
}
if ((data->msgs[0].buf = (unsigned char *)malloc(2 * sizeof(unsigned char))) == NULL) { ret = -1;
goto errexit1;
}
data->msgs[0].addr = addr;
data->msgs[0].flags = 0;
data->msgs[0].len = 2;
data->msgs[0].buf[0] = offset;
data->msgs[0].buf[1] = val;
if ((ret = __i2c_send(fd, data)) < 0)
goto errexit0;
errexit0:
free(data->msgs[0].buf);
errexit1:
free(data->msgs);
errexit2:
free(data);
return ret;
}
int
i2c_open(unsigned char* dev, unsigned int timeout, unsigned int retry) {
if ((fd = open(dev, O_RDWR)) < 0)
return fd;
__i2c_set(fd, timeout, retry);
return fd;
}
static int
__i2c_send(int fd, struct i2c_rdwr_ioctl_data *data)
{
if (fd < 0)
return -1;
if (data == NULL)
return -1;
if (data->msgs == NULL || data->nmsgs == 0)
return -1;
return ioctl(fd, I2C_RDWR, (unsigned long)data) ;
}
static int
__i2c_set(int fd, unsigned int timeout, unsigned int retry)
{
if (fd == 0 )
return -1;
ioctl(fd, I2C_TIMEOUT, timeout ? timeout : I2C_DEFAULT_TIMEOUT);
ioctl(fd, I2C_RETRIES, retry ? retry : I2C_DEFAULT_RETRY);
return 0;
}
void
i2c_close(int fd)
{
if (fd < 0)
return;
close(fd);
}
********* ****************************************************** #ifndef I2C_H
#define I2C_H
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/rtc.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#define I2C_DEFAULT_TIMEOUT1
#define I2C_DEFAULT_RETRY3
#define PCF8563_REG_SC 0x02
#define PCF8563_REG_MN 0x03
#define PCF8563_REG_HR 0x04
#define PCF8563_REG_DM 0x05
#define PCF8563_REG_DW 0x06
#define PCF8563_REG_MO 0x07
#define PCF8563_REG_YR 0x08
#define PCF8563_MO_C 0x80
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
static const unsigned char rtc_days_in_month[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
unsigned bcd2bin(unsigned char val);
unsigned bcd2bin(unsigned char val);
static int
__i2c_send(int fd, struct i2c_rdwr_ioctl_data *data);
static int
__i2c_set(int fd, unsigned int timeout, unsigned int retry);
int
i2c_read_data(u16 addr, u8 offset, u8 *val);
int
i2c_write_data(u16 addr, u8 offset, u8 val);
int
i2c_open(unsigned char* dev, unsigned int timeout, unsigned int retry);
#endif
******* **************************************************************************。

相关文档
最新文档