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

QQ登錄

只需一步,快速開(kāi)始

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

關(guān)于單片機(jī)UART和IIC EEPROM和UART的應(yīng)用,有一些疑惑,請(qǐng)各位朋友幫忙指點(diǎn)一下

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:415088 發(fā)表于 2020-5-28 17:13 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
80黑幣
用串口調(diào)試助手,將數(shù)據(jù)通過(guò)UART下發(fā)到單片機(jī)當(dāng)中, 并且存儲(chǔ)到EEPROM中, 然后將電源關(guān)掉, 重新上電讀取EEPROM的數(shù)據(jù)并數(shù)碼管上顯示出來(lái),但是我現(xiàn)在數(shù)據(jù)發(fā)送單片機(jī)也接收了,就是無(wú)法存儲(chǔ)到EEPROM中,望各位朋友幫忙指點(diǎn)一下,謝謝!

以下是單片機(jī)代碼:

----------------------------------------------------------
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
  4. sbit I2C_SCL = P0^6;
  5. sbit I2C_SDA = P0^7;

  6. unsigned char ucDataOneTab[10] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f};
  7. unsigned char ucDataTwoTab[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
  8. unsigned char disbuf[8] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07};

  9. sbit LED_SMG_RCK = P1^0;
  10. sbit LED_SMG_SCK = P1^1;
  11. sbit LED_SMG_DATA = P1^4;

  12. unsigned char RxdByte;

  13. //數(shù)碼管顯示函數(shù)
  14. void Send_data_smg(unsigned int uiDataOne,unsigned int uiDataTwo)
  15. {
  16.         unsigned char i;
  17.         
  18.         LED_SMG_RCK = 0;
  19.         for(i=0; i<8; i++)
  20.         {
  21.                 LED_SMG_SCK = 0;
  22.                 if(0 != (uiDataOne&0x80))
  23.                 {
  24.                         LED_SMG_DATA = 1;
  25.                 }
  26.                 else
  27.                 {
  28.                         LED_SMG_DATA = 0;
  29.                 }
  30.                 LED_SMG_SCK = 1;
  31.                 uiDataOne <<= 1;
  32.         }
  33.         
  34.         for(i=0; i<8; i++)
  35.         {
  36.                 LED_SMG_SCK = 0;
  37.                 if(0 != (uiDataTwo&0x80))
  38.                 {
  39.                         LED_SMG_DATA = 1;
  40.                 }
  41.                 else
  42.                 {
  43.                         LED_SMG_DATA = 0;
  44.                 }
  45.                 LED_SMG_SCK = 1;
  46.                 uiDataTwo <<= 1;
  47.         }
  48.         LED_SMG_RCK = 1;        
  49. }

  50. /* 產(chǎn)生總線起始信號(hào) */
  51. void I2CStart()
  52. {
  53.         I2C_SDA = 1; //首先確保 SDA、 SCL 都是高電平
  54.         I2C_SCL = 1;
  55.         I2CDelay();
  56.         I2C_SDA = 0; //先拉低 SDA
  57.         I2CDelay();
  58.         I2C_SCL = 0; //再拉低 SCL
  59. }

  60. /* 產(chǎn)生總線停止信號(hào) */
  61. void I2CStop()
  62. {
  63.         I2C_SCL = 0; //首先確保 SDA、 SCL 都是低電平
  64.         I2C_SDA = 0;
  65.         I2CDelay();
  66.         I2C_SCL = 1; //先拉高 SCL
  67.         I2CDelay();
  68.         I2C_SDA = 1; //再拉高 SDA
  69.         I2CDelay();
  70. }

  71. /* I2C 總線寫(xiě)操作, dat-待寫(xiě)入字節(jié),返回值-從機(jī)應(yīng)答位的值 */
  72. bit I2CWrite(unsigned char dat)
  73. {
  74.         bit ack; //用于暫存應(yīng)答位的值
  75.         unsigned char mask; //用于探測(cè)字節(jié)內(nèi)某一位值的掩碼變量
  76.         for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進(jìn)行
  77.         {
  78.                 if ((mask&dat) == 0) //該位的值輸出到 SDA 上
  79.                         I2C_SDA = 0;
  80.                 else
  81.                         I2C_SDA = 1;
  82.                
  83.                 I2CDelay();
  84.                 I2C_SCL = 1; //拉高 SCL
  85.                 I2CDelay();
  86.                 I2C_SCL = 0; //再拉低 SCL,完成一個(gè)位周期
  87.         }
  88.         I2C_SDA = 1; //8 位數(shù)據(jù)發(fā)送完后,主機(jī)釋放 SDA,以檢測(cè)從機(jī)應(yīng)答
  89.         I2CDelay();
  90.         I2C_SCL = 1; //拉高 SCL
  91.         ack = I2C_SDA; //讀取此時(shí)的 SDA 值,即為從機(jī)的應(yīng)答值
  92.         I2CDelay();
  93.         I2C_SCL = 0; //再拉低 SCL 完成應(yīng)答位,并保持住總線
  94.         return (~ack); //應(yīng)答值取反以符合通常的邏輯:
  95.         //0=不存在或忙或?qū)懭胧。?1=存在且空閑或?qū)懭氤晒?br />
  96. }


  97. /* I2C 總線讀操作,并發(fā)送非應(yīng)答信號(hào),返回值-讀到的字節(jié) */
  98. unsigned char I2CReadNAK()
  99. {
  100.         unsigned char mask;
  101.         unsigned char dat;
  102.         I2C_SDA = 1; //首先確保主機(jī)釋放 SDA
  103.         for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進(jìn)行
  104.         {
  105.                 I2CDelay();
  106.                 I2C_SCL = 1; //拉高 SCL
  107.                 if(I2C_SDA == 0) //讀取 SDA 的值
  108.                         dat &= ~mask; //為 0 時(shí), dat 中對(duì)應(yīng)位清零
  109.                 else
  110.                         dat |= mask; //為 1 時(shí), dat 中對(duì)應(yīng)位置 1
  111.                 I2CDelay();
  112.                 I2C_SCL = 0; //再拉低 SCL,以使從機(jī)發(fā)送出下一位
  113.         }
  114.         I2C_SDA = 1; //8 位數(shù)據(jù)發(fā)送完后,拉高 SDA,發(fā)送非應(yīng)答信號(hào)
  115.         I2CDelay();
  116.         I2C_SCL = 1; //拉高 SCL
  117.         I2CDelay();
  118.         I2C_SCL = 0; //再拉低 SCL 完成非應(yīng)答位,并保持住總線
  119.         return dat;
  120. }

  121. /* I2C 總線讀操作,并發(fā)送應(yīng)答信號(hào),返回值-讀到的字節(jié) */
  122. unsigned char I2CReadACK()
  123. {
  124.         unsigned char mask;
  125.         unsigned char dat;
  126.         I2C_SDA = 1; //首先確保主機(jī)釋放 SDA
  127.         for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進(jìn)行
  128.         {
  129.         I2CDelay();
  130.         I2C_SCL = 1; //拉高 SCL
  131.         if(I2C_SDA == 0) //讀取 SDA 的值
  132.                 dat &= ~mask; //為 0 時(shí), dat 中對(duì)應(yīng)位清零
  133.         else
  134.                 dat |= mask; //為 1 時(shí), dat 中對(duì)應(yīng)位置 1
  135.         I2CDelay();
  136.         I2C_SCL = 0; //再拉低 SCL,以使從機(jī)發(fā)送出下一位
  137.         }
  138.         I2C_SDA = 0; //8 位數(shù)據(jù)發(fā)送完后,拉低 SDA,發(fā)送應(yīng)答信號(hào)
  139.         I2CDelay();
  140.         I2C_SCL = 1; //拉高 SCL
  141.         I2CDelay();
  142.         I2C_SCL = 0; //再拉低 SCL 完成應(yīng)答位,并保持住總線
  143.         
  144.         return dat;
  145. }

  146. /* 讀取 EEPROM 中的一個(gè)字節(jié), addr-字節(jié)地址 */
  147. unsigned char E2ReadByte(unsigned char addr)
  148. {
  149.         unsigned char dat;
  150.         I2CStart();
  151.         I2CWrite(0x50<<1); //尋址器件,后續(xù)為寫(xiě)操作
  152.         I2CWrite(addr); //寫(xiě)入存儲(chǔ)地址
  153.         I2CStart(); //發(fā)送重復(fù)啟動(dòng)信號(hào)
  154.         I2CWrite((0x50<<1)|0x01); //尋址器件,后續(xù)為讀操作
  155.         dat = I2CReadNAK(); //讀取一個(gè)字節(jié)數(shù)據(jù)
  156.         I2CStop();
  157.         return dat;
  158. }

  159. /* 向 EEPROM 中寫(xiě)入一個(gè)字節(jié), addr-字節(jié)地址 */
  160. void E2WriteByte(unsigned char addr, unsigned char dat)
  161. {
  162.         I2CStart();
  163.         I2CWrite(0x50<<1); //尋址器件,后續(xù)為寫(xiě)操作
  164.         I2CWrite(addr); //寫(xiě)入存儲(chǔ)地址
  165.         I2CWrite(dat); //寫(xiě)入一個(gè)字節(jié)數(shù)據(jù)
  166.         I2CStop();
  167. }

  168. void Delay1ms(unsigned int i)
  169. {
  170.     int j;
  171.     for(; i>0; i--)
  172.          {
  173.          for(j = 0; j < 110; j++);
  174.     }
  175. }

  176. void ConfigUart(unsigned int baud)
  177. {
  178.         SCON = 0x50;
  179.         TMOD &= 0x0F;
  180.         TMOD |= 0x20;
  181.         TH1 = 256 - (11059200/12/32)/baud;
  182.         TL1 = TH1;
  183.         TR1 = 1;
  184.         ET1 = 0;
  185.         ES = 1;
  186. }

  187. void main()
  188. {
  189.         unsigned char dat;
  190.         unsigned char i;
  191.         unsigned char str[5];
  192.         
  193.         EA = 1;
  194.         ConfigUart(9600);
  195.         
  196.         RxdByte = E2ReadByte(0x20);
  197.         Delay1ms(100);
  198.                
  199.         str[0] = (RxdByte/100);
  200.         str[1] = (RxdByte/10%10);
  201.         str[2] = (RxdByte%10);
  202.         
  203.         //dat++;
  204.         E2WriteByte(0x20,RxdByte);//將數(shù)據(jù)存儲(chǔ)到E2PROM中
  205.         disbuf[2] = ucDataOneTab[str[2]];
  206.         disbuf[1] = ucDataOneTab[str[1]];
  207.         disbuf[0] = ucDataOneTab[str[0]];
  208.         
  209.         while(1)
  210.         {
  211.                 for(i=0; i<8; i++)
  212.                 {
  213.                         Send_data_smg(disbuf[i],ucDataTwoTab[i]);
  214.                         Delay1ms(1);
  215.                 }               
  216.         }
  217. }

  218. /* UART中斷服務(wù)函數(shù) */
  219. void InterruptUART() interrupt 4
  220. {
  221.     if (RI)  //接收到字節(jié)
  222.     {
  223.         RI = 0;          //手動(dòng)清零接收中斷標(biāo)志位
  224.         RxdByte = SBUF;  //接收到的數(shù)據(jù)保存到接收字節(jié)變量中
  225.                          //用以提示用戶輸入的信息是否已正確接收
  226.           SBUF = RxdByte;
  227.     }
  228.     if (TI)  //字節(jié)發(fā)送完畢
  229.     {
  230.         TI = 0;  //手動(dòng)清零發(fā)送中斷標(biāo)志位
  231.     }
  232. }
復(fù)制代碼





分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:415088 發(fā)表于 2020-5-28 19:25 | 只看該作者
/* UART中斷服務(wù)函數(shù) */
void InterruptUART() interrupt 4
{
    if (RI)  //接收到字節(jié)
    {
        RI = 0;          //手動(dòng)清零接收中斷標(biāo)志位
        RxdByte = SBUF;  //接收到的數(shù)據(jù)保存到接收字節(jié)變量中
                         //用以提示用戶輸入的信息是否已正確接收
                SBUF = RxdByte;
                E2WriteByte(0x10,RxdByte);
    }
    if (TI)  //字節(jié)發(fā)送完畢
    {
        TI = 0;  //手動(dòng)清零發(fā)送中斷標(biāo)志位
    }
}
這樣子就可以了
回復(fù)

使用道具 舉報(bào)

板凳
ID:282850 發(fā)表于 2020-5-29 10:13 | 只看該作者
細(xì)看了E2WriteByte在main中只調(diào)了一次。加在UART中解決了,無(wú)問(wèn)題?
回復(fù)

使用道具 舉報(bào)

地板
ID:415088 發(fā)表于 2020-6-1 21:57 | 只看該作者
f556 發(fā)表于 2020-5-29 10:13
細(xì)看了E2WriteByte在main中只調(diào)了一次。加在UART中解決了,無(wú)問(wèn)題?

但是我加在中斷接收里面后,確實(shí)是可以達(dá)到我的題目要求了
回復(fù)

使用道具 舉報(bào)

5#
ID:801878 發(fā)表于 2020-7-13 19:31 | 只看該作者
加一個(gè)中斷 {     if (RI)  //接收到字節(jié)     {         RI = 0;          //手動(dòng)清零接收中斷標(biāo)志位         RxdByte = SBUF;  //接收到的數(shù)據(jù)保存到接收字節(jié)變量中                          //用以提示用戶輸入的信息是否已正確接收                 SBUF = RxdByte;                 E2WriteByte(0x10,RxdByte);
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表