|
void DS1302_WriteByte(uint8_t addr) { uint8_t i=0; for(i=0;i<8;i++) { if(addr&0x01) { DATA_H; } else { DATA_L; } addr>>=1; SCLK_H; SCLK_L; } } uint8_t DS1302_ReadByte() { uint8_t i=0,date=0; for(i=0;i<8;i++) { date >>=1; if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)) { date |=0x80; } SCLK_H; SCLK_L; } return date; } void DS1302_BURST_Read(uint8_t *dat) { uint8_t i=0; CE_H; DS1302_DAT_GPIO_Out(); DS1302_WriteByte(0x8f); DS1302_DAT_GPIO_IN(); for(i=0;i<8;i++) { dat[i]=DS1302_ReadByte(); } CE_L; } 我这个为什么BURST不行 |
188610329 发表于 2021-9-12 22:43 非常感谢,太谢谢了 之前数码管显示的是年月日,数值一直没动,没发现问题,昨天夜里把显示改成时分秒,发现秒虽然是乱码,但一直在有规律的跳动,记录倒推了一下才发现是读取时高低位顺序反了。 我之前说字节读取正确是用仿照教程写的按字节读取方式的代码能正确读出。这个burst模式的代码是我自己写的。我之前一直以为是没有读到数据,所以检查的方向错了。 多谢耐心指正 |
vyo 发表于 2021-9-12 18:39 你个/////!! ///////了, 你说你字节读取时正确的??? 你的 DS1302ByteRead() 压根是错的,你居然说字节读取能正确,用这个代码你能正确读取??…… 你把DS1302ByteRead()里面循环节如下修改: for(i=0;i<8;i++) //循环8次读取8组数据 { dat >>= 1; //先右移 !!!!!!!!!!! 不是左移 if (DS1302_IO) dat |=0x80; //判断IO口数据是否为1, 为1置1高位,否则不动 DS1302_SCLK = 1; //拉高锁存器电平产生上升沿,读入数据 DS1302_SCLK = 0; //拉高锁存器电平产生上升沿,读入数据 } 最后说一下,DS1302 的时钟比较特别,写一个地址的内容, 地址+数据,其实总共只有 15个半时钟。读一个地址的内容, 地址+内容,其实总共只有15个时钟,两种方式都不是用满16个时钟,你这种强改时钟的方式,我以前强迫症状况下也作过,后来发现,强行16个时钟,下一次的读操作很容易被误判写操作。如果写保护位不置80的话,在没有数据口上拉电阻情况下,很容易误写0xff 到DS1302,。这个是后话了,你先搞定眼前的吧,总之,如果要完全按照手册的时序,代码会多很多。你之后如果,不需要频繁改内容的话,就写保护置0x80吧。要改时间了再置0。 |
|
uint8 DS1302ByteRead() { uint8 i; uint8 dat=0; //先给dat赋值 0X00 即 0000 0000 // DS1302_SCLK=0; //拉低锁存器电平准备写入数据 for(i=0;i<8;i++) //循环8次读取8组数据 { if (DS1302_IO == 0) //判断IO口数据是否为0 { dat = dat << 1; //如果IO口为0,dat左移1位,左移最低位默认补0 } else { dat = dat << 1; //如果IO口不为0,dat左移1位,最低位先补个0 dat = dat | 0x01; //最低位或上0x01,最低位变成1 } DS1302_SCLK = 1; //拉高锁存器电平产生上升沿,读入数据 DS1302_SCLK = 0; //拉高锁存器电平产生上升沿,读入数据 } return dat; //返回读取到的时间数据数组 } 读的时候,是低位开始读,所以你要高位开始写, for(i=0;i<8;i++) //循环8次读取8组数据 { dat >>= 1; //数据右移 if (DS1302_IO) dat |= 0x80; //判断IO口数据是否为1,唯一高位置1,反之啥也不干 DS1302_SCLK = 1; //拉高锁存器电平产生上升沿,读入数据 DS1302_SCLK = 0; //拉高锁存器电平产生上升沿,读入数据 } |
|
用Burst 读取,有两个比较 重要的注意点。 1, 发送 0xBF 或者 0xff 前, 在拉高 CE 之后, CLK 动作之前, 先拉低数据传授口 IO = 0(如果每次读到错误值都一样,就是这个问题); 然后再开始发送, 0xBF 或者 0xFF. 2, 条件如果允许, 数据串口IO 上拉10K电阻到 VCC , 然后选择模式为开漏, 如果硬件上改造比较难,那么在Burst 读取时,确保, 每次 CLK = 0 之后, 等待时间 0.5us 之后 再去 读 IO 的值(没有上拉电阻这点很重要,如果你每次读到的错误值没有规律,就是这个问题。),读完一个字节之后,等待 2us 之后再继续读下一个字节(这个你用C语言写代码的话到基本不用特别考虑,肯定会超过2us)。 |