熱門: 51單片機(jī) | 24小時(shí)必答區(qū) | 單片機(jī)教程 | 單片機(jī)DIY制作 | STM32 | Cortex M3 | 模數(shù)電子 | 電子DIY制作 | 音響/功放 | 拆機(jī)樂園 | Arduino | 嵌入式OS | 程序設(shè)計(jì)
|
發(fā)布時(shí)間: 2021-9-12 11:21
正文摘要:用字節(jié)讀取模式可以正常讀取,burst模式能寫,但是讀出來是亂碼。 一下是代碼,哪位學(xué)長有空幫忙看下。 /********************************************************************* ... |
|
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; } 我這個(gè)為什么BURST不行 |
188610329 發(fā)表于 2021-9-12 22:43 非常感謝,太謝謝了 之前數(shù)碼管顯示的是年月日,數(shù)值一直沒動(dòng),沒發(fā)現(xiàn)問題,昨天夜里把顯示改成時(shí)分秒,發(fā)現(xiàn)秒雖然是亂碼,但一直在有規(guī)律的跳動(dòng),記錄倒推了一下才發(fā)現(xiàn)是讀取時(shí)高低位順序反了。 我之前說字節(jié)讀取正確是用仿照教程寫的按字節(jié)讀取方式的代碼能正確讀出。這個(gè)burst模式的代碼是我自己寫的。我之前一直以為是沒有讀到數(shù)據(jù),所以檢查的方向錯(cuò)了。 多謝耐心指正 |
vyo 發(fā)表于 2021-9-12 18:39 你個(gè)/////!! ///////了, 你說你字節(jié)讀取時(shí)正確的??? 你的 DS1302ByteRead() 壓根是錯(cuò)的,你居然說字節(jié)讀取能正確,用這個(gè)代碼你能正確讀取??…… 你把DS1302ByteRead()里面循環(huán)節(jié)如下修改: for(i=0;i<8;i++) //循環(huán)8次讀取8組數(shù)據(jù) { dat >>= 1; //先右移 !!!!!!!!!!! 不是左移 if (DS1302_IO) dat |=0x80; //判斷IO口數(shù)據(jù)是否為1, 為1置1高位,否則不動(dòng) DS1302_SCLK = 1; //拉高鎖存器電平產(chǎn)生上升沿,讀入數(shù)據(jù) DS1302_SCLK = 0; //拉高鎖存器電平產(chǎn)生上升沿,讀入數(shù)據(jù) } 最后說一下,DS1302 的時(shí)鐘比較特別,寫一個(gè)地址的內(nèi)容, 地址+數(shù)據(jù),其實(shí)總共只有 15個(gè)半時(shí)鐘。讀一個(gè)地址的內(nèi)容, 地址+內(nèi)容,其實(shí)總共只有15個(gè)時(shí)鐘,兩種方式都不是用滿16個(gè)時(shí)鐘,你這種強(qiáng)改時(shí)鐘的方式,我以前強(qiáng)迫癥狀況下也作過,后來發(fā)現(xiàn),強(qiáng)行16個(gè)時(shí)鐘,下一次的讀操作很容易被誤判寫操作。如果寫保護(hù)位不置80的話,在沒有數(shù)據(jù)口上拉電阻情況下,很容易誤寫0xff 到DS1302,。這個(gè)是后話了,你先搞定眼前的吧,總之,如果要完全按照手冊(cè)的時(shí)序,代碼會(huì)多很多。你之后如果,不需要頻繁改內(nèi)容的話,就寫保護(hù)置0x80吧。要改時(shí)間了再置0。 |
|
uint8 DS1302ByteRead() { uint8 i; uint8 dat=0; //先給dat賦值 0X00 即 0000 0000 // DS1302_SCLK=0; //拉低鎖存器電平準(zhǔn)備寫入數(shù)據(jù) for(i=0;i<8;i++) //循環(huán)8次讀取8組數(shù)據(jù) { if (DS1302_IO == 0) //判斷IO口數(shù)據(jù)是否為0 { dat = dat << 1; //如果IO口為0,dat左移1位,左移最低位默認(rèn)補(bǔ)0 } else { dat = dat << 1; //如果IO口不為0,dat左移1位,最低位先補(bǔ)個(gè)0 dat = dat | 0x01; //最低位或上0x01,最低位變成1 } DS1302_SCLK = 1; //拉高鎖存器電平產(chǎn)生上升沿,讀入數(shù)據(jù) DS1302_SCLK = 0; //拉高鎖存器電平產(chǎn)生上升沿,讀入數(shù)據(jù) } return dat; //返回讀取到的時(shí)間數(shù)據(jù)數(shù)組 } 讀的時(shí)候,是低位開始讀,所以你要高位開始寫, for(i=0;i<8;i++) //循環(huán)8次讀取8組數(shù)據(jù) { dat >>= 1; //數(shù)據(jù)右移 if (DS1302_IO) dat |= 0x80; //判斷IO口數(shù)據(jù)是否為1,唯一高位置1,反之啥也不干 DS1302_SCLK = 1; //拉高鎖存器電平產(chǎn)生上升沿,讀入數(shù)據(jù) DS1302_SCLK = 0; //拉高鎖存器電平產(chǎn)生上升沿,讀入數(shù)據(jù) } |
|
用Burst 讀取,有兩個(gè)比較 重要的注意點(diǎn)。 1, 發(fā)送 0xBF 或者 0xff 前, 在拉高 CE 之后, CLK 動(dòng)作之前, 先拉低數(shù)據(jù)傳授口 IO = 0(如果每次讀到錯(cuò)誤值都一樣,就是這個(gè)問題); 然后再開始發(fā)送, 0xBF 或者 0xFF. 2, 條件如果允許, 數(shù)據(jù)串口IO 上拉10K電阻到 VCC , 然后選擇模式為開漏, 如果硬件上改造比較難,那么在Burst 讀取時(shí),確保, 每次 CLK = 0 之后, 等待時(shí)間 0.5us 之后 再去 讀 IO 的值(沒有上拉電阻這點(diǎn)很重要,如果你每次讀到的錯(cuò)誤值沒有規(guī)律,就是這個(gè)問題。),讀完一個(gè)字節(jié)之后,等待 2us 之后再繼續(xù)讀下一個(gè)字節(jié)(這個(gè)你用C語言寫代碼的話到基本不用特別考慮,肯定會(huì)超過2us)。 |
Powered by 單片機(jī)教程網(wǎng)