标题:
关于单片机UART和IIC EEPROM和UART的应用,有一些疑惑,请各位朋友帮忙指点一下
[打印本页]
作者:
八月初
时间:
2020-5-28 17:13
标题:
关于单片机UART和IIC EEPROM和UART的应用,有一些疑惑,请各位朋友帮忙指点一下
用串口调试助手,将数据通过UART下发到单片机当中, 并且存储到EEPROM中, 然后将电源关掉, 重新上电读取EEPROM的数据并数码管上显示出来,但是我现在数据发送单片机也接收了,就是无法存储到EEPROM中,望各位朋友帮忙指点一下,谢谢!
以下是单片机代码:
----------------------------------------------------------
#include <reg52.h>
#include <intrins.h>
#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P0^6;
sbit I2C_SDA = P0^7;
unsigned char ucDataOneTab[10] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f};
unsigned char ucDataTwoTab[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
unsigned char disbuf[8] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07};
sbit LED_SMG_RCK = P1^0;
sbit LED_SMG_SCK = P1^1;
sbit LED_SMG_DATA = P1^4;
unsigned char RxdByte;
//数码管显示函数
void Send_data_smg(unsigned int uiDataOne,unsigned int uiDataTwo)
{
unsigned char i;
LED_SMG_RCK = 0;
for(i=0; i<8; i++)
{
LED_SMG_SCK = 0;
if(0 != (uiDataOne&0x80))
{
LED_SMG_DATA = 1;
}
else
{
LED_SMG_DATA = 0;
}
LED_SMG_SCK = 1;
uiDataOne <<= 1;
}
for(i=0; i<8; i++)
{
LED_SMG_SCK = 0;
if(0 != (uiDataTwo&0x80))
{
LED_SMG_DATA = 1;
}
else
{
LED_SMG_DATA = 0;
}
LED_SMG_SCK = 1;
uiDataTwo <<= 1;
}
LED_SMG_RCK = 1;
}
/* 产生总线起始信号 */
void I2CStart()
{
I2C_SDA = 1; //首先确保 SDA、 SCL 都是高电平
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 0; //先拉低 SDA
I2CDelay();
I2C_SCL = 0; //再拉低 SCL
}
/* 产生总线停止信号 */
void I2CStop()
{
I2C_SCL = 0; //首先确保 SDA、 SCL 都是低电平
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1; //先拉高 SCL
I2CDelay();
I2C_SDA = 1; //再拉高 SDA
I2CDelay();
}
/* I2C 总线写操作, dat-待写入字节,返回值-从机应答位的值 */
bit I2CWrite(unsigned char dat)
{
bit ack; //用于暂存应答位的值
unsigned char mask; //用于探测字节内某一位值的掩码变量
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{
if ((mask&dat) == 0) //该位的值输出到 SDA 上
I2C_SDA = 0;
else
I2C_SDA = 1;
I2CDelay();
I2C_SCL = 1; //拉高 SCL
I2CDelay();
I2C_SCL = 0; //再拉低 SCL,完成一个位周期
}
I2C_SDA = 1; //8 位数据发送完后,主机释放 SDA,以检测从机应答
I2CDelay();
I2C_SCL = 1; //拉高 SCL
ack = I2C_SDA; //读取此时的 SDA 值,即为从机的应答值
I2CDelay();
I2C_SCL = 0; //再拉低 SCL 完成应答位,并保持住总线
return (~ack); //应答值取反以符合通常的逻辑:
//0=不存在或忙或写入失败, 1=存在且空闲或写入成功
}
/* I2C 总线读操作,并发送非应答信号,返回值-读到的字节 */
unsigned char I2CReadNAK()
{
unsigned char mask;
unsigned char dat;
I2C_SDA = 1; //首先确保主机释放 SDA
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{
I2CDelay();
I2C_SCL = 1; //拉高 SCL
if(I2C_SDA == 0) //读取 SDA 的值
dat &= ~mask; //为 0 时, dat 中对应位清零
else
dat |= mask; //为 1 时, dat 中对应位置 1
I2CDelay();
I2C_SCL = 0; //再拉低 SCL,以使从机发送出下一位
}
I2C_SDA = 1; //8 位数据发送完后,拉高 SDA,发送非应答信号
I2CDelay();
I2C_SCL = 1; //拉高 SCL
I2CDelay();
I2C_SCL = 0; //再拉低 SCL 完成非应答位,并保持住总线
return dat;
}
/* I2C 总线读操作,并发送应答信号,返回值-读到的字节 */
unsigned char I2CReadACK()
{
unsigned char mask;
unsigned char dat;
I2C_SDA = 1; //首先确保主机释放 SDA
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{
I2CDelay();
I2C_SCL = 1; //拉高 SCL
if(I2C_SDA == 0) //读取 SDA 的值
dat &= ~mask; //为 0 时, dat 中对应位清零
else
dat |= mask; //为 1 时, dat 中对应位置 1
I2CDelay();
I2C_SCL = 0; //再拉低 SCL,以使从机发送出下一位
}
I2C_SDA = 0; //8 位数据发送完后,拉低 SDA,发送应答信号
I2CDelay();
I2C_SCL = 1; //拉高 SCL
I2CDelay();
I2C_SCL = 0; //再拉低 SCL 完成应答位,并保持住总线
return dat;
}
/* 读取 EEPROM 中的一个字节, addr-字节地址 */
unsigned char E2ReadByte(unsigned char addr)
{
unsigned char dat;
I2CStart();
I2CWrite(0x50<<1); //寻址器件,后续为写操作
I2CWrite(addr); //写入存储地址
I2CStart(); //发送重复启动信号
I2CWrite((0x50<<1)|0x01); //寻址器件,后续为读操作
dat = I2CReadNAK(); //读取一个字节数据
I2CStop();
return dat;
}
/* 向 EEPROM 中写入一个字节, addr-字节地址 */
void E2WriteByte(unsigned char addr, unsigned char dat)
{
I2CStart();
I2CWrite(0x50<<1); //寻址器件,后续为写操作
I2CWrite(addr); //写入存储地址
I2CWrite(dat); //写入一个字节数据
I2CStop();
}
void Delay1ms(unsigned int i)
{
int j;
for(; i>0; i--)
{
for(j = 0; j < 110; j++);
}
}
void ConfigUart(unsigned int baud)
{
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 256 - (11059200/12/32)/baud;
TL1 = TH1;
TR1 = 1;
ET1 = 0;
ES = 1;
}
void main()
{
unsigned char dat;
unsigned char i;
unsigned char str[5];
EA = 1;
ConfigUart(9600);
RxdByte = E2ReadByte(0x20);
Delay1ms(100);
str[0] = (RxdByte/100);
str[1] = (RxdByte/10%10);
str[2] = (RxdByte%10);
//dat++;
E2WriteByte(0x20,RxdByte);//将数据存储到E2PROM中
disbuf[2] = ucDataOneTab[str[2]];
disbuf[1] = ucDataOneTab[str[1]];
disbuf[0] = ucDataOneTab[str[0]];
while(1)
{
for(i=0; i<8; i++)
{
Send_data_smg(disbuf[i],ucDataTwoTab[i]);
Delay1ms(1);
}
}
}
/* UART中断服务函数 */
void InterruptUART() interrupt 4
{
if (RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
RxdByte = SBUF; //接收到的数据保存到接收字节变量中
//用以提示用户输入的信息是否已正确接收
SBUF = RxdByte;
}
if (TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
复制代码
作者:
八月初
时间:
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; //手动清零发送中断标志位
}
}
这样子就可以了
作者:
f556
时间:
2020-5-29 10:13
细看了E2WriteByte在main中只调了一次。加在UART中解决了,无问题?
作者:
八月初
时间:
2020-6-1 21:57
f556 发表于 2020-5-29 10:13
细看了E2WriteByte在main中只调了一次。加在UART中解决了,无问题?
但是我加在中断接收里面后,确实是可以达到我的题目要求了
作者:
乐儿翅
时间:
2020-7-13 19:31
加一个中断 { if (RI) //接收到字节 { RI = 0; //手动清零接收中断标志位 RxdByte = SBUF; //接收到的数据保存到接收字节变量中 //用以提示用户输入的信息是否已正确接收 SBUF = RxdByte; E2WriteByte(0x10,RxdByte);
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1