博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ARM裸板开发:07_IIC 通过IIC总线接口读写时钟芯片时间参数实现的总结
阅读量:6914 次
发布时间:2019-06-27

本文共 7364 字,大约阅读时间需要 24 分钟。

问题一:程序直接在iRAM内部可正常执行,而程序搬移(Nand ->SDRAM)之后,就不能正常运行了
#define NAND_SECTOR_SIZE    2048 /* 读函数 */void nand_read(unsigned char *buf, unsigned long start_addr, int size){    int i, j; //if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))     if (start_addr & NAND_BLOCK_MASK)        return;    /* 地址不对齐则退出 */     /* 选中芯片 */    nand_select_chip();     for(i=start_addr; i < (start_addr + size);)    {      /* 发出READ0命令 */      write_cmd(0);      /* Write Address */      write_addr(i);            write_cmd(0x30);       /* 等待数据就绪 */      wait_idle();       for(j=0; j < NAND_SECTOR_SIZE; j++, i++)      {          *buf = read_data();          buf++;      }    }     /* 取消片选信号 */    nand_disselect_chip();        return;}
查看韦东山nand_read代码,发现有这样一条语句:
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
        return;    /* 地址或大小不对齐则退出 */
而在start.S中,size = __bss_start - 0x30000000,这个大小显然不能保证是2048的倍数(事实确也如此,并不是2048的倍数,也就导致了nand_read函数并未正常执行)
地址或大小不对齐则退出,这种方式有问题,大小确实也没必要对齐。若大小刚好超出一个块内存,就将这个块内存完整copy即可。
 
问题二:ARM9裸板开发过程,硬件并不不支持除法运算,所以除法以及取余操作如何实现?
/** val    : 需要转换的整形值* bit    : 该整形值的位数* pdst    : 转换字符串输出*/void int_to_str(int val, unsigned char bit, char *pdst){    //根据val位数确定mult. E.G. val-1位 -> mult=1    int mult;    for (mult = 1; --bit != 0; mult *= 10);     for ( ; mult != 0; mult /= 10)    {        *pdst++ = (char)(val/mult + '0');        val %= mult;    }}
1、网上搜了一些方法,基本思想是运用移位运算,比较,以及乘法操作等实现。
比如:sum / 6    可转换为    sum * (1 / 6)    (1 / 6) -> (5461 / 32768),而 1/32768 即为(1 >> 15)。这种方法主要是通过将分数转换为被除数是2的次幂的方式实现的,有误差。
2、使用库函数。参考韦东山的方式,在07_IIC工程中添加
include
lib两个依赖库。同时修改对应地Makefile文件,可以正常编译通过。
#Time: 2018-4-19 11:56:52#Proj: General Makefile#Designed by DZH for JZ2440 #Define varsTARGET_NAME    := iic#final targetTARGET    := $(TARGET_NAME).bin#temp targetBUILD    := $(TARGET_NAME).elf#disa targetDISA    := $(TARGET_NAME).dis #default boot from NAND FlashENV        ?= NAND OBJS    += start.oOBJS    += init.oOBJS    += main.oOBJS    += iic.oOBJS    += nand.oOBJS    += serial.oOBJS    += m41t11.oOBJS    += irq_handler.oOBJS    += lib/libc.a CROSS_COMPILE := arm-linux-CC            := $(CROSS_COMPILE)gccLD            := $(CROSS_COMPILE)ldAR          := $(CROSS_COMPILE)arOBJCOPY        := $(CROSS_COMPILE)objcopyOBJDUMP        := $(CROSS_COMPILE)objdump #warningINCLUDEDIR     := $(shell pwd)/includeCCFLAGS    += -nostdinc -I$(INCLUDEDIR)CCFLAGS    += -Wall -O2# 不加-O2优化,链接过程报错:# lib/libc.a(string.o)(.text+0x38): In function `puts':# : undefined reference to `putc' #basic address#ifeq ($(ENV), NAND)#LDFLAGS    += -Ttext=0x0#else#LDFLAGS    += -Ttext=0xXXX#endifLDFLAGS    += -Tmap.lds export     CC LD OBJCOPY OBJDUMP INCLUDEDIR CCFLAGS AR #Compile wayall : $(DISA) $(TARGET)$(DISA)    : $(BUILD)    $(OBJDUMP) -D $^ > $@ $(TARGET) : $(BUILD)    $(OBJCOPY) -O binary -S $^ $@ $(BUILD) : $(OBJS)    $(LD) $(LDFLAGS) -o $@ $^ .PHONY : lib/libc.alib/libc.a:    cd lib; make; cd .. %.o : %.S    $(CC) $(CCFLAGS) -c -o $@ $^%.o : %.c    $(CC) $(CCFLAGS) -c -o $@ $^    clean:    make  clean -C lib    rm -f $(TARGET) $(BUILD) $(DISA) *.o
其中加粗部分是为了将除法和取余运算的依赖库包含进来所执行的操作。
 
此外,为了实现时间参数的写入和读出,封装了几个有效的转换函数:
1、string -> int
/** pstr    : 字符串首地址,空字符结束* len    : 字符串有效字符长度*/int str_to_int(const char *pstr, unsigned char len){    unsigned int ret = 0;    unsigned int mult;        //根据pstr长度确定mult. E.G. pstr-1位 -> mult=1    for (mult = 1; --len != 0; mult *= 10);        for ( ;*pstr != '\0'; ++pstr)    {        ret += (unsigned int)(*pstr - '0') * mult;        mult /= 10;    }     return (int)ret;}
 
2、int -> string
/** val    : 需要转换的整形值* bit    : 该整形值的位数* pdst    : 转换字符串输出*/void int_to_str(int val, unsigned char bit, char *pdst){    //根据val位数确定mult. E.G. val-1位 -> mult=1    int mult;    for (mult = 1; --bit != 0; mult *= 10);     for ( ; mult != 0; mult /= 10)    {        *pdst++ = (char)(val/mult + '0');        val %= mult;    }}
 
3、参数设置时间参数结构体变量,
将字符串类型的时间参数装换为对应的整形值
需要写入的时间参数格式:E.G.(year-mon-day-week-hour-min-sec): 2018 05 15 2 13 29 00,数值间以空格键分开
struct rtc_time {    int tm_sec;    int tm_min;    int tm_hour;    int tm_week;    int tm_mday;    int tm_mon;    int tm_year;};
void set_rtc_time(char *pstr, struct rtc_time *prtc){    char *ptmp = pstr;    char s_time[25];    unsigned char i;    unsigned char len[7] = {
0}; //1. 分拆时间字符串 for ( i = 0; *ptmp != '\0'; ++ptmp) { if (*ptmp != ' ') len[i]++; else { *ptmp = '\0'; ++i; } } //2. 设置对应rtc时间参数 send_l(pstr); prtc->tm_year = str_to_int(pstr, len[0]); pstr += len[0] + 1; prtc->tm_mon = str_to_int(pstr, len[1]); pstr += len[1] + 1; prtc->tm_mday = str_to_int(pstr, len[2]); pstr += len[2] + 1; prtc->tm_week = str_to_int(pstr, len[3]); pstr += len[3] + 1; prtc->tm_hour = str_to_int(pstr, len[4]); pstr += len[4] + 1; prtc->tm_min = str_to_int(pstr, len[5]); pstr += len[5] + 1; prtc->tm_sec = str_to_int(pstr, len[6]);}void set_time(void){ char s_time[30] = {
0}; send_l("E.G.(year-mon-day-week-hour-min-sec): 2018 5 15 2 13 29 0"); recv_l(s_time); send_s("Input: "); send_l(s_time); set_rtc_time(s_time, &g_rtc_time); m41t11_set_datetime(&g_rtc_time);}
由于时钟芯片m41t11可能不能正常工作(写入时间无效),故修改set_rtc_time函数作为测试函数如下
void set_rtc_time(char *pstr, struct rtc_time *prtc){    char *ptmp = pstr;    char s_time[25];    unsigned char i;    unsigned char len[7] = {
0}; //1. 分拆时间字符串 for ( i = 0; *ptmp != '\0'; ++ptmp) { if (*ptmp != ' ') len[i]++; else { *ptmp = '\0'; ++i; } } //2. 设置对应rtc时间参数 send_l(pstr); prtc->tm_year = str_to_int(pstr, len[0]); pstr += len[0] + 1; send_l(pstr); prtc->tm_mon = str_to_int(pstr, len[1]); pstr += len[1] + 1; send_l(pstr); prtc->tm_mday = str_to_int(pstr, len[2]); pstr += len[2] + 1; send_l(pstr); prtc->tm_week = str_to_int(pstr, len[3]); pstr += len[3] + 1; send_l(pstr); prtc->tm_hour = str_to_int(pstr, len[4]); pstr += len[4] + 1; send_l(pstr); prtc->tm_min = str_to_int(pstr, len[5]); pstr += len[5] + 1; send_l(pstr); prtc->tm_sec = str_to_int(pstr, len[6]); get_rtc_time(&g_rtc_time, s_time); send_s("g_rtc_time: "); send_l(s_time);}
 
3、读取时间参数结构体变量,并将其装换为字符串
void get_rtc_time(const struct rtc_time *prtc, char *pdst){    //格式: 2018-05-15 2 19:30:00    int_to_str(prtc->tm_year, 4, pdst);    *(pdst+4) = '-';    int_to_str(prtc->tm_mon, 2, pdst+5);    *(pdst+7) = '-';    int_to_str(prtc->tm_mday, 2, pdst+8);    *(pdst+10) = ' ';    int_to_str(prtc->tm_week, 1, pdst+11);    *(pdst+12) = ' ';    int_to_str(prtc->tm_hour, 2, pdst+13);    *(pdst+15) = ':';    int_to_str(prtc->tm_min, 2, pdst+16);    *(pdst+18) = ':';    int_to_str(prtc->tm_sec, 2, pdst+19);    *(pdst+21) = '\0';} void show_time(void){    //格式: 2018-05-15 2 13:29:00    char s_time[25] = {
0}; send_s("Now is: "); m41t11_get_datetime(&g_rtc_time); get_rtc_time(&g_rtc_time, s_time); send_l(s_time);}
 
最终实现的效果如下:
1、菜单界面
          
2、[R]ead  data&time.
            
3、[W]rite data&time.
      
从以上结果可以看出,int 与 string 之间的转换函数均可正常工作。
其中最后一行的 g_rtc_time 参数,是逆向转换后的输出结果,能够说明写入m41t11时钟芯片的参数没有问题
m41t11_set_datetime(&g_rtc_time);
不过之后读出的结果并没有发生改变:
      
故猜测可能是由于m41t11时钟芯片原因所致(不过纽扣电池电量不足应该可以排除,否则应该不能从中读出数据吧?这个并没有兴趣折腾了)

转载于:https://www.cnblogs.com/Glory-D/p/9062245.html

你可能感兴趣的文章
安全测试===如何查看浏览器保存的密码
查看>>
POJ3177 Redundant Paths【双连通分量】
查看>>
El表达式的用法个人总结
查看>>
object - c 语言基础 进阶笔记 随笔笔记
查看>>
iOS开发之--一些有用的博文和博客
查看>>
jmeter JDBC Request (查询数据库获取数据库数据) 的使用
查看>>
深入理解ajax系列第七篇——传递JSON
查看>>
Vim简明学习
查看>>
16.文件file
查看>>
PHP-FPM@year12
查看>>
Reportviewer中的函数使用——打印当前日期并格式化
查看>>
oracle用户管理
查看>>
15.Intellij中配置jdk/tomcat/maven
查看>>
GridView中实现CheckBox的全选
查看>>
home.pl 正在促销,一些域名免费(终止于2017.4.4)
查看>>
python、js 时间日期模块time
查看>>
Loadrunner监控Centos
查看>>
转:问题解决:The project cannot be built until build path errors are resolved
查看>>
Python--day25--面向对象之多态
查看>>
submit
查看>>