找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1610|回复: 4
打印 上一主题 下一主题
收起左侧

关于单片机UART和IIC EEPROM和UART的应用,有一些疑惑,请各位朋友帮忙指点一下

[复制链接]
跳转到指定楼层
楼主
ID:415088 发表于 2020-5-28 17:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
80黑币
用串口调试助手,将数据通过UART下发到单片机当中, 并且存储到EEPROM中, 然后将电源关掉, 重新上电读取EEPROM的数据并数码管上显示出来,但是我现在数据发送单片机也接收了,就是无法存储到EEPROM中,望各位朋友帮忙指点一下,谢谢!

以下是单片机代码:

----------------------------------------------------------
  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. //数码管显示函数
  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. /* 产生总线起始信号 */
  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. /* 产生总线停止信号 */
  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 总线写操作, dat-待写入字节,返回值-从机应答位的值 */
  72. bit I2CWrite(unsigned char dat)
  73. {
  74.         bit ack; //用于暂存应答位的值
  75.         unsigned char mask; //用于探测字节内某一位值的掩码变量
  76.         for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
  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,完成一个位周期
  87.         }
  88.         I2C_SDA = 1; //8 位数据发送完后,主机释放 SDA,以检测从机应答
  89.         I2CDelay();
  90.         I2C_SCL = 1; //拉高 SCL
  91.         ack = I2C_SDA; //读取此时的 SDA 值,即为从机的应答值
  92.         I2CDelay();
  93.         I2C_SCL = 0; //再拉低 SCL 完成应答位,并保持住总线
  94.         return (~ack); //应答值取反以符合通常的逻辑:
  95.         //0=不存在或忙或写入失败, 1=存在且空闲或写入成功
  96. }


  97. /* I2C 总线读操作,并发送非应答信号,返回值-读到的字节 */
  98. unsigned char I2CReadNAK()
  99. {
  100.         unsigned char mask;
  101.         unsigned char dat;
  102.         I2C_SDA = 1; //首先确保主机释放 SDA
  103.         for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
  104.         {
  105.                 I2CDelay();
  106.                 I2C_SCL = 1; //拉高 SCL
  107.                 if(I2C_SDA == 0) //读取 SDA 的值
  108.                         dat &= ~mask; //为 0 时, dat 中对应位清零
  109.                 else
  110.                         dat |= mask; //为 1 时, dat 中对应位置 1
  111.                 I2CDelay();
  112.                 I2C_SCL = 0; //再拉低 SCL,以使从机发送出下一位
  113.         }
  114.         I2C_SDA = 1; //8 位数据发送完后,拉高 SDA,发送非应答信号
  115.         I2CDelay();
  116.         I2C_SCL = 1; //拉高 SCL
  117.         I2CDelay();
  118.         I2C_SCL = 0; //再拉低 SCL 完成非应答位,并保持住总线
  119.         return dat;
  120. }

  121. /* I2C 总线读操作,并发送应答信号,返回值-读到的字节 */
  122. unsigned char I2CReadACK()
  123. {
  124.         unsigned char mask;
  125.         unsigned char dat;
  126.         I2C_SDA = 1; //首先确保主机释放 SDA
  127.         for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
  128.         {
  129.         I2CDelay();
  130.         I2C_SCL = 1; //拉高 SCL
  131.         if(I2C_SDA == 0) //读取 SDA 的值
  132.                 dat &= ~mask; //为 0 时, dat 中对应位清零
  133.         else
  134.                 dat |= mask; //为 1 时, dat 中对应位置 1
  135.         I2CDelay();
  136.         I2C_SCL = 0; //再拉低 SCL,以使从机发送出下一位
  137.         }
  138.         I2C_SDA = 0; //8 位数据发送完后,拉低 SDA,发送应答信号
  139.         I2CDelay();
  140.         I2C_SCL = 1; //拉高 SCL
  141.         I2CDelay();
  142.         I2C_SCL = 0; //再拉低 SCL 完成应答位,并保持住总线
  143.         
  144.         return dat;
  145. }

  146. /* 读取 EEPROM 中的一个字节, addr-字节地址 */
  147. unsigned char E2ReadByte(unsigned char addr)
  148. {
  149.         unsigned char dat;
  150.         I2CStart();
  151.         I2CWrite(0x50<<1); //寻址器件,后续为写操作
  152.         I2CWrite(addr); //写入存储地址
  153.         I2CStart(); //发送重复启动信号
  154.         I2CWrite((0x50<<1)|0x01); //寻址器件,后续为读操作
  155.         dat = I2CReadNAK(); //读取一个字节数据
  156.         I2CStop();
  157.         return dat;
  158. }

  159. /* 向 EEPROM 中写入一个字节, addr-字节地址 */
  160. void E2WriteByte(unsigned char addr, unsigned char dat)
  161. {
  162.         I2CStart();
  163.         I2CWrite(0x50<<1); //寻址器件,后续为写操作
  164.         I2CWrite(addr); //写入存储地址
  165.         I2CWrite(dat); //写入一个字节数据
  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);//将数据存储到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中断服务函数 */
  219. void InterruptUART() interrupt 4
  220. {
  221.     if (RI)  //接收到字节
  222.     {
  223.         RI = 0;          //手动清零接收中断标志位
  224.         RxdByte = SBUF;  //接收到的数据保存到接收字节变量中
  225.                          //用以提示用户输入的信息是否已正确接收
  226.           SBUF = RxdByte;
  227.     }
  228.     if (TI)  //字节发送完毕
  229.     {
  230.         TI = 0;  //手动清零发送中断标志位
  231.     }
  232. }
复制代码





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:415088 发表于 2020-5-28 19:25 | 只看该作者
/* UART中断服务函数 */
void InterruptUART() interrupt 4
{
    if (RI)  //接收到字节
    {
        RI = 0;          //手动清零接收中断标志位
        RxdByte = SBUF;  //接收到的数据保存到接收字节变量中
                         //用以提示用户输入的信息是否已正确接收
                SBUF = RxdByte;
                E2WriteByte(0x10,RxdByte);
    }
    if (TI)  //字节发送完毕
    {
        TI = 0;  //手动清零发送中断标志位
    }
}
这样子就可以了
回复

使用道具 举报

板凳
ID:282850 发表于 2020-5-29 10:13 | 只看该作者
细看了E2WriteByte在main中只调了一次。加在UART中解决了,无问题?
回复

使用道具 举报

地板
ID:415088 发表于 2020-6-1 21:57 | 只看该作者
f556 发表于 2020-5-29 10:13
细看了E2WriteByte在main中只调了一次。加在UART中解决了,无问题?

但是我加在中断接收里面后,确实是可以达到我的题目要求了
回复

使用道具 举报

5#
ID:801878 发表于 2020-7-13 19:31 | 只看该作者
加一个中断 {     if (RI)  //接收到字节     {         RI = 0;          //手动清零接收中断标志位         RxdByte = SBUF;  //接收到的数据保存到接收字节变量中                          //用以提示用户输入的信息是否已正确接收                 SBUF = RxdByte;                 E2WriteByte(0x10,RxdByte);
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表