久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 3691|回復(fù): 17
打印 上一主題 下一主題
收起左側(cè)

這個(gè)C語言代碼怎么理解:DS1302ByteWrite((reg<<1)|0x80)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
/* 用單次寫操作向某一寄存器寫入一個(gè)字節(jié),reg-寄存器地址,dat-待寫入字節(jié) */
void DS1302SingleWrite(unsigned char reg, unsigned char dat)
{
DS1302_CE = 1; //使能片選信號(hào)
DS1302ByteWrite((reg<<1)|0x80); //發(fā)送寫寄存器指令
DS1302ByteWrite(dat); //寫入字節(jié)數(shù)據(jù)
DS1302_CE = 0; //除能片選信號(hào)
}
其中DS1302ByteWrite((reg<<1)|0x80),這個(gè)怎么理解?REG為什么要左移一位再或上0X80?
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:752974 發(fā)表于 2023-2-20 14:51 | 只看該作者
左移一位是扔掉了REG的最高位,再或0X80是將移位后的REG的最高位置1,。
回復(fù)

使用道具 舉報(bào)

板凳
ID:213173 發(fā)表于 2023-2-20 15:11 | 只看該作者
讀出地址:0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d
寫入地址:0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c
變量reg如果等于0x00,左移一位還是0x00,0x00|0x80 等于0x80
變量reg如果等于0x01,左移一位是0x02,0x02|0x80 等于0x82
變量reg如果等于0x02,左移一位是0x04,0x04|0x80 等于0x84
......以此類推。
回復(fù)

使用道具 舉報(bào)

地板
ID:69038 發(fā)表于 2023-2-20 15:35 | 只看該作者
沒有完整代碼不好說,據(jù)猜測應(yīng)是1302的讀寫地址不一樣,才這么做的,比如定義的秒的寫地址為80,讀是81,如果是這樣,那代碼是不行的,要(reg|0x01)才對(duì),大小端搞錯(cuò)了。
回復(fù)

使用道具 舉報(bào)

5#
ID:673647 發(fā)表于 2023-2-20 15:37 | 只看該作者
wulin 發(fā)表于 2023-2-20 15:11
讀出地址:0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d
寫入地址:0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x ...

謝謝,也就是說DS1302讀和寫的寄存器地址一共有16個(gè)(80h~8fh),逐個(gè)讀出來嗎?默認(rèn)的初始地址不一定是0X80啊?也沒有循環(huán)語句,為什么要這樣寫呢?
回復(fù)

使用道具 舉報(bào)

6#
ID:673647 發(fā)表于 2023-2-20 15:38 | 只看該作者
munuc_w 發(fā)表于 2023-2-20 14:51
左移一位是扔掉了REG的最高位,再或0X80是將移位后的REG的最高位置1,。

謝謝!REG的值是多少?為什么要扔掉最高位呢?
回復(fù)

使用道具 舉報(bào)

7#
ID:673647 發(fā)表于 2023-2-20 15:41 | 只看該作者
zhuls 發(fā)表于 2023-2-20 15:35
沒有完整代碼不好說,據(jù)猜測應(yīng)是1302的讀寫地址不一樣,才這么做的,比如定義的秒的寫地址為80,讀是81,如 ...

完整代碼如下:
  1. #include <reg52.h>
  2. sbit DS1302_CE = P1^7;
  3. sbit DS1302_CK = P3^5;
  4. sbit DS1302_IO = P3^4;
  5. bit flag200ms = 0; //200ms 定時(shí)標(biāo)志
  6. unsigned char T0RH = 0; //T0 重載值的高字節(jié)
  7. unsigned char T0RL = 0; //T0 重載值的低字節(jié)
  8. void ConfigTimer0(unsigned int ms);
  9. void InitDS1302();
  10. unsigned char DS1302SingleRead(unsigned char reg);
  11. extern void InitLcd1602();
  12. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
  13. void main()
  14. {
  15. unsigned char i;
  16. unsigned char psec=0xAA; //秒備份,初值 AA 確保首次讀取時(shí)間后會(huì)刷新顯示
  17. unsigned char time[8]; //當(dāng)前時(shí)間數(shù)組
  18. unsigned char str[12]; //字符串轉(zhuǎn)換緩沖區(qū)
  19. EA = 1; //開總中斷
  20. ConfigTimer0(1); //T0 定時(shí) 1ms
  21. InitDS1302(); //初始化實(shí)時(shí)時(shí)鐘
  22. InitLcd1602(); //初始化液晶

  23. while (1)
  24. {
  25. if (flag200ms) //每 200ms 讀取一次時(shí)間
  26. {
  27. flag200ms = 0;
  28. for (i=0; i<7; i++) //讀取 DS1302 當(dāng)前時(shí)間
  29. {
  30. time[i] = DS1302SingleRead(i);
  31. }
  32. if (psec != time[0]) //檢測到時(shí)間有變化時(shí)刷新顯示
  33. {
  34. str[0] = '2'; //添加年份的高 2 位:20
  35. str[1] = '0';
  36. str[2] = (time[6] >> 4) + '0'; //“年”高位數(shù)字轉(zhuǎn)換為 ASCII 碼
  37. str[3] = (time[6]&0x0F) + '0'; //“年”低位數(shù)字轉(zhuǎn)換為 ASCII 碼
  38. str[4] = '-'; //添加日期分隔符
  39. str[5] = (time[4] >> 4) + '0'; //“月”
  40. str[6] = (time[4]&0x0F) + '0';
  41. str[7] = '-';
  42. str[8] = (time[3] >> 4) + '0'; //“日”
  43. str[9] = (time[3]&0x0F) + '0';
  44. str[10] = '\0';
  45. LcdShowStr(0, 0, str); //顯示到液晶的第一行

  46. str[0] = (time[5]&0x0F) + '0'; //“星期”
  47. str[1] = '\0';
  48. LcdShowStr(11, 0, "week");
  49. LcdShowStr(15, 0, str); //顯示到液晶的第一行

  50. str[0] = (time[2] >> 4) + '0'; //“時(shí)”
  51. str[1] = (time[2]&0x0F) + '0';
  52. str[2] = ':'; //添加時(shí)間分隔符
  53. str[3] = (time[1] >> 4) + '0'; //“分”
  54. str[4] = (time[1]&0x0F) + '0';
  55. str[5] = ':';
  56. str[6] = (time[0] >> 4) + '0'; //“秒”
  57. str[7] = (time[0]&0x0F) + '0';
  58. str[8] = '\0';
  59. LcdShowStr(4, 1, str); //顯示到液晶的第二行

  60. psec = time[0]; //用當(dāng)前值更新上次秒數(shù)
  61. }
  62. }
  63. }
  64. }
  65. /* 發(fā)送一個(gè)字節(jié)到 DS1302 通信總線上 */
  66. void DS1302ByteWrite(unsigned char dat)
  67. {
  68. unsigned char mask;

  69. for (mask=0x01; mask!=0; mask<<=1) //低位在前,逐位移出
  70. {
  71. if ((mask&dat) != 0) //首先輸出該位數(shù)據(jù)
  72. DS1302_IO = 1;
  73. else
  74. DS1302_IO = 0;
  75. DS1302_CK = 1; //然后拉高時(shí)鐘
  76. DS1302_CK = 0; //再拉低時(shí)鐘,完成一個(gè)位的操作
  77. }
  78. DS1302_IO = 1; //最后確保釋放 IO 引腳
  79. }
  80. /* 由 DS1302 通信總線上讀取一個(gè)字節(jié) */
  81. unsigned char DS1302ByteRead()
  82. {
  83. unsigned char mask;
  84. unsigned char dat = 0;

  85. for (mask=0x01; mask!=0; mask<<=1) //低位在前,逐位讀取
  86. {
  87. if (DS1302_IO != 0) //首先讀取此時(shí)的 IO 引腳,并設(shè)置 dat 中的對(duì)應(yīng)位
  88. {
  89. dat |= mask;
  90. }
  91. DS1302_CK = 1; //然后拉高時(shí)鐘
  92. DS1302_CK = 0; //再拉低時(shí)鐘,完成一個(gè)位的操作
  93. }
  94. return dat; //最后返回讀到的字節(jié)數(shù)據(jù)
  95. }
  96. /* 用單次寫操作向某一寄存器寫入一個(gè)字節(jié),reg-寄存器地址,dat-待寫入字節(jié) */
  97. void DS1302SingleWrite(unsigned char reg, unsigned char dat)
  98. {
  99. DS1302_CE = 1; //使能片選信號(hào)
  100. DS1302ByteWrite((reg<<1)|0x80); //發(fā)送寫寄存器指令
  101. DS1302ByteWrite(dat); //寫入字節(jié)數(shù)據(jù)
  102. DS1302_CE = 0; //除能片選信號(hào)
  103. }
  104. /* 用單次讀操作從某一寄存器讀取一個(gè)字節(jié),reg-寄存器地址,返回值-讀到的字節(jié) */
  105. unsigned char DS1302SingleRead(unsigned char reg)
  106. {
  107. unsigned char dat;
  108. DS1302_CE = 1; //使能片選信號(hào)
  109. DS1302ByteWrite((reg<<1)|0x81); //發(fā)送讀寄存器指令
  110. dat = DS1302ByteRead(); //讀取字節(jié)數(shù)據(jù)
  111. DS1302_CE = 0; //除能片選信號(hào)

  112. return dat;
  113. }
  114. /* DS1302 初始化,如發(fā)生掉電則重新設(shè)置初始時(shí)間 */
  115. void InitDS1302()
  116. {
  117. unsigned char i;
  118. unsigned char code InitTime[] = { //2013 年 10 月 8 日 星期二 12:30:00
  119. 0x00,0x30,0x12, 0x08, 0x10, 0x02, 0x13
  120. };

  121. DS1302_CE = 0; //初始化 DS1302 通信引腳
  122. DS1302_CK = 0;
  123. i = DS1302SingleRead(0); //讀取秒寄存器
  124. if ((i & 0x80) != 0) //由秒寄存器最高位 CH 的值判斷 DS1302 是否已停止
  125. {
  126. DS1302SingleWrite(7, 0x00); //撤銷寫保護(hù)以允許寫入數(shù)據(jù)
  127. for (i=0; i<7; i++) //設(shè)置 DS1302 為默認(rèn)的初始時(shí)間
  128. {
  129. DS1302SingleWrite(i, InitTime[i]);
  130. }
  131. }
  132. }
  133. /* 配置并啟動(dòng) T0,ms-T0 定時(shí)時(shí)間 */
  134. void ConfigTimer0(unsigned int ms)
  135. {
  136. unsigned long tmp; //臨時(shí)變量

  137. tmp = 11059200 / 12; //定時(shí)器計(jì)數(shù)頻率
  138. tmp = (tmp * ms) / 1000; //計(jì)算所需的計(jì)數(shù)值
  139. tmp = 65536 - tmp; //計(jì)算定時(shí)器重載值
  140. tmp = tmp + 12; //補(bǔ)償中斷響應(yīng)延時(shí)造成的誤差
  141. T0RH = (unsigned char)(tmp>>8); //定時(shí)器重載值拆分為高低字節(jié)
  142. T0RL = (unsigned char)tmp;
  143. TMOD &= 0xF0; //清零 T0 的控制位
  144. TMOD |= 0x01; //配置 T0 為模式 1
  145. TH0 = T0RH; //加載 T0 重載值
  146. TL0 = T0RL;
  147. ET0 = 1; //使能 T0 中斷
  148. TR0 = 1; //啟動(dòng) T0
  149. }
  150. /* T0 中斷服務(wù)函數(shù),執(zhí)行 200ms 定時(shí) */
  151. void InterruptTimer0() interrupt 1
  152. {
  153. static unsigned char tmr200ms = 0;

  154. TH0 = T0RH; //重新加載重載值
  155. TL0 = T0RL;
  156. tmr200ms++;
  157. if (tmr200ms >= 200) //定時(shí) 200ms
  158. {
  159. tmr200ms = 0;
  160. flag200ms = 1;
  161. }
  162. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

8#
ID:69038 發(fā)表于 2023-2-20 15:41 | 只看該作者
wulin 發(fā)表于 2023-2-20 15:11
讀出地址:0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d
寫入地址:0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x ...

學(xué)習(xí)了~~那定義寫入地址,讀時(shí)直接地址+1不就OK了?還整這么多彎彎,
回復(fù)

使用道具 舉報(bào)

9#
ID:752974 發(fā)表于 2023-2-20 16:52 | 只看該作者
cwb2038 發(fā)表于 2023-2-20 15:38
謝謝!REG的值是多少?為什么要扔掉最高位呢?

這個(gè)要看芯片的指令格式。
回復(fù)

使用道具 舉報(bào)

10#
ID:596109 發(fā)表于 2023-2-20 17:17 | 只看該作者
應(yīng)該是這個(gè)寄存器的最低位必須寫0,最高位必須是1,reg保存的是中間6位有效指令,剛好加起來是8位
回復(fù)

使用道具 舉報(bào)

11#
ID:213173 發(fā)表于 2023-2-20 17:22 | 只看該作者
zhuls 發(fā)表于 2023-2-20 15:41
學(xué)習(xí)了~~那定義寫入地址,讀時(shí)直接地址+1不就OK了?還整這么多彎彎,

這是各人編程習(xí)慣的差異,沒有好差之分。
回復(fù)

使用道具 舉報(bào)

12#
ID:673647 發(fā)表于 2023-2-20 18:43 | 只看該作者
munuc_w 發(fā)表于 2023-2-20 16:52
這個(gè)要看芯片的指令格式。

謝謝指點(diǎn),但還是有點(diǎn)不是很理解!搞不清楚為什么要這樣寫,這是DS1302的寄存器介紹,能再解釋一下嗎?
15.3.3 DS1302 寄存器介紹

DS1302 的一條指令一個(gè)字節(jié)共 8 位,其中第 7 位(即最高位)固定為 1,這一位如果是
0 的話,那寫進(jìn)去也是無效的。第 6 位是選擇 RAM 還是 CLOCK 的,我前邊說過,我們這里
主要講 CLOCK 時(shí)鐘的使用,它的 RAM 功能我們不用,所以如果選擇 CLOCK 功能,第 6
位是 0,如果要用 RAM,那第 6 位就是 1。從第 5 到第 1 位,決定了寄存器的 5 位地址,而
第 0 位是讀寫位,如果要寫,這一位就是 0,如果要讀,這一位就是 1。指令字節(jié)直觀位分
配如圖 15-9 所示。
圖 15-9 DS1302 命令字節(jié)
DS1302 時(shí)鐘的寄存器,其中 8 個(gè)和時(shí)鐘有關(guān)的,5 位地址分別是 0b00000~0b00111,還
有一個(gè)寄存器的地址是 01000,這是涓流充電所用的寄存器,我們這里不講。在 DS1302 的
數(shù)據(jù)手冊(cè)里的地址,直接把第 7 位、第 6 位和第 0 位值給出來了,所以指令就成了 0x80、0x81
那些了,最低位是 1,那么表示讀,最低位是 0 表示寫,如圖 15-10 所示。
圖 15-10 DS1302 的時(shí)鐘寄存器


寄存器 0:最高位 CH 是一個(gè)時(shí)鐘停止標(biāo)志位。如果時(shí)鐘電路有備用電源,上電后,我
們要先檢測一下這一位,如果這一位是 0,那說明時(shí)鐘芯片在系統(tǒng)掉電后,由于備用電源的
供給,時(shí)鐘是持續(xù)正常運(yùn)行的;如果這一位是 1,那么說明時(shí)鐘芯片在系統(tǒng)掉電后,時(shí)鐘部
分不工作了。如果 Vcc1 懸空或者是電池沒電了,當(dāng)我們下次重新上電時(shí),讀取這一位,那
這一位就是 1,我們可以通過這一位判斷時(shí)鐘在單片機(jī)系統(tǒng)掉電后是否還正常運(yùn)行。剩下的
7 位高 3 位是秒的十位,低 4 位是秒的個(gè)位,這里再提請(qǐng)注意一次,DS1302 內(nèi)部是 BCD 碼,
而秒的十位最大是 5,所以 3 個(gè)二進(jìn)制位就夠了。
寄存器 1:最高位未使用,剩下的 7 位中高 3 位是分鐘的十位,低 4 位是分鐘的個(gè)位。
寄存器 2:bit7 是 1 的話代表是 12 小時(shí)制,0 代表是 24 小時(shí)制;bit6 固定是 0,bit5 在
12 小時(shí)制下 0 代表的是上午,1 代表的是下午,在 24 小時(shí)制下和 bit4 一起代表了小時(shí)的十
位,低 4 位代表的是小時(shí)的個(gè)位。
寄存器 3:高 2 位固定是 0,bit5 和 bit4 是日期的十位,低 4 位是日期的個(gè)位。
寄存器 4:高 3 位固定是 0,bit4 是月的十位,低 4 位是月的個(gè)位。
寄存器 5:高 5 位固定是 0,低 3 位代表了星期。
寄存器 6:高 4 位代表了年的十位,低 4 位代表了年的個(gè)位。請(qǐng)?zhí)貏e注意,這里的 00~
99 指的是 2000 年~2099 年。
寄存器 7:最高位一個(gè)寫保護(hù)位,如果這一位是 1,那么是禁止給任何其它寄存器或者
那 31 個(gè)字節(jié)的 RAM 寫數(shù)據(jù)的。因此在寫數(shù)據(jù)之前,這一位必須先寫成 0。
回復(fù)

使用道具 舉報(bào)

13#
ID:213173 發(fā)表于 2023-2-20 21:48 | 只看該作者

你看明白下列語句,前面的問題就解決了
  1.                 DS1302SingleWrite(7, 0x00); //撤銷寫保護(hù)以允許寫入數(shù)據(jù)  【 地址7<<1|0x80等于0x8E 】
  2.                 for (i=0; i<7; i++) //設(shè)置 DS1302 為默認(rèn)的初始時(shí)間
  3.                 {
  4.                         DS1302SingleWrite(i, InitTime[i]); //【 地址i<<1|0x80等于0x80,0x82,0x84,0x86,0x88,0x8A,0x8C】
  5.                 }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

14#
ID:161164 發(fā)表于 2023-2-20 23:34 | 只看該作者
cwb2038 發(fā)表于 2023-2-20 18:43
謝謝指點(diǎn),但還是有點(diǎn)不是很理解!搞不清楚為什么要這樣寫,這是DS1302的寄存器介紹,能再解釋一下嗎?
...

把命令值化作二進(jìn)制就清楚了


回復(fù)

使用道具 舉報(bào)

15#
ID:673647 發(fā)表于 2023-2-21 11:09 | 只看該作者
wulin 發(fā)表于 2023-2-20 21:48
你看明白下列語句,前面的問題就解決了

謝謝,有點(diǎn)明白了!
回復(fù)

使用道具 舉報(bào)

16#
ID:673647 發(fā)表于 2023-2-21 11:17 | 只看該作者
lkc8210 發(fā)表于 2023-2-20 23:34
把命令值化作二進(jìn)制就清楚了

謝謝解答!還想請(qǐng)教一下,你這命令值怎么轉(zhuǎn)化過來的?DS1302寄存器不是有5位,A4~A0嗎?你說的“Address:A2~A0”是指什么?
回復(fù)

使用道具 舉報(bào)

17#
ID:161164 發(fā)表于 2023-2-21 11:38 | 只看該作者
cwb2038 發(fā)表于 2023-2-21 11:17
謝謝解答!還想請(qǐng)教一下,你這命令值怎么轉(zhuǎn)化過來的?DS1302寄存器不是有5位,A4~A0嗎?你說的“Address ...

這表是HT1381的寄存器表,但和DS1302的有99.999%相似,所以拿來示范
命令值只是16進(jìn)制轉(zhuǎn)2進(jìn)制,如0x80=0B10000000
A4~A0對(duì)應(yīng)命令值bit5~bit1
可以看得到A4,A3全是零,所以只看A2~A0就可以了
回復(fù)

使用道具 舉報(bào)

18#
ID:673647 發(fā)表于 2023-2-21 14:35 | 只看該作者
lkc8210 發(fā)表于 2023-2-21 11:38
這表是HT1381的寄存器表,但和DS1302的有99.999%相似,所以拿來示范
命令值只是16進(jìn)制轉(zhuǎn)2進(jìn)制,如0x80=0 ...

哦,謝謝!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产黄色av网站 | 毛片一级网站 | 天天干天天草 | 国产精品视频免费观看 | 97国产在线观看 | 亚洲第一天堂 | 奇米av| 国产综合久久 | 日韩久久精品电影 | 日韩精品一区二区三区中文字幕 | 午夜影院黄 | 久久在线免费 | 一区二区三区四区视频 | 日韩欧美国产不卡 | 日本黄色片免费在线观看 | 91精品国产综合久久婷婷香蕉 | 亚洲精品久久 | a级在线免费 | 久久99精品视频 | 黄a免费网络 | 亚洲精品久久久久久久久久久 | 久久国产精品一区二区三区 | 日本三级在线网站 | 精品欧美色视频网站在线观看 | 久久久91精品国产一区二区三区 | 国产探花在线精品一区二区 | 亚洲人在线 | 免费视频一区 | 欧美日韩视频在线 | 一区二区三区免费 | 欧美日韩亚洲视频 | 干干干日日日 | 日韩精品一区二区三区在线观看 | av中文在线 | 插插插干干干 | 97精品超碰一区二区三区 | 91国在线高清视频 | 亚洲成av人影片在线观看 | 91精品一区 | 久久夜视频 | 一级黄色生活视频 |