標(biāo)題:
關(guān)于單片機UART和IIC EEPROM和UART的應(yīng)用,有一些疑惑,請各位朋友幫忙指點一下
[打印本頁]
作者:
八月初
時間:
2020-5-28 17:13
標(biāo)題:
關(guān)于單片機UART和IIC EEPROM和UART的應(yīng)用,有一些疑惑,請各位朋友幫忙指點一下
用串口調(diào)試助手,將數(shù)據(jù)通過UART下發(fā)到單片機當(dāng)中, 并且存儲到EEPROM中, 然后將電源關(guān)掉, 重新上電讀取EEPROM的數(shù)據(jù)并數(shù)碼管上顯示出來,但是我現(xiàn)在數(shù)據(jù)發(fā)送單片機也接收了,就是無法存儲到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;
//數(shù)碼管顯示函數(shù)
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;
}
/* 產(chǎn)生總線起始信號 */
void I2CStart()
{
I2C_SDA = 1; //首先確保 SDA、 SCL 都是高電平
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 0; //先拉低 SDA
I2CDelay();
I2C_SCL = 0; //再拉低 SCL
}
/* 產(chǎn)生總線停止信號 */
void I2CStop()
{
I2C_SCL = 0; //首先確保 SDA、 SCL 都是低電平
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1; //先拉高 SCL
I2CDelay();
I2C_SDA = 1; //再拉高 SDA
I2CDelay();
}
/* I2C 總線寫操作, dat-待寫入字節(jié),返回值-從機應(yīng)答位的值 */
bit I2CWrite(unsigned char dat)
{
bit ack; //用于暫存應(yīng)答位的值
unsigned char mask; //用于探測字節(jié)內(nèi)某一位值的掩碼變量
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 位數(shù)據(jù)發(fā)送完后,主機釋放 SDA,以檢測從機應(yīng)答
I2CDelay();
I2C_SCL = 1; //拉高 SCL
ack = I2C_SDA; //讀取此時的 SDA 值,即為從機的應(yīng)答值
I2CDelay();
I2C_SCL = 0; //再拉低 SCL 完成應(yīng)答位,并保持住總線
return (~ack); //應(yīng)答值取反以符合通常的邏輯:
//0=不存在或忙或?qū)懭胧。?1=存在且空閑或?qū)懭氤晒?br />
}
/* I2C 總線讀操作,并發(fā)送非應(yīng)答信號,返回值-讀到的字節(jié) */
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 中對應(yīng)位清零
else
dat |= mask; //為 1 時, dat 中對應(yīng)位置 1
I2CDelay();
I2C_SCL = 0; //再拉低 SCL,以使從機發(fā)送出下一位
}
I2C_SDA = 1; //8 位數(shù)據(jù)發(fā)送完后,拉高 SDA,發(fā)送非應(yīng)答信號
I2CDelay();
I2C_SCL = 1; //拉高 SCL
I2CDelay();
I2C_SCL = 0; //再拉低 SCL 完成非應(yīng)答位,并保持住總線
return dat;
}
/* I2C 總線讀操作,并發(fā)送應(yīng)答信號,返回值-讀到的字節(jié) */
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 中對應(yīng)位清零
else
dat |= mask; //為 1 時, dat 中對應(yīng)位置 1
I2CDelay();
I2C_SCL = 0; //再拉低 SCL,以使從機發(fā)送出下一位
}
I2C_SDA = 0; //8 位數(shù)據(jù)發(fā)送完后,拉低 SDA,發(fā)送應(yīng)答信號
I2CDelay();
I2C_SCL = 1; //拉高 SCL
I2CDelay();
I2C_SCL = 0; //再拉低 SCL 完成應(yīng)答位,并保持住總線
return dat;
}
/* 讀取 EEPROM 中的一個字節(jié), addr-字節(jié)地址 */
unsigned char E2ReadByte(unsigned char addr)
{
unsigned char dat;
I2CStart();
I2CWrite(0x50<<1); //尋址器件,后續(xù)為寫操作
I2CWrite(addr); //寫入存儲地址
I2CStart(); //發(fā)送重復(fù)啟動信號
I2CWrite((0x50<<1)|0x01); //尋址器件,后續(xù)為讀操作
dat = I2CReadNAK(); //讀取一個字節(jié)數(shù)據(jù)
I2CStop();
return dat;
}
/* 向 EEPROM 中寫入一個字節(jié), addr-字節(jié)地址 */
void E2WriteByte(unsigned char addr, unsigned char dat)
{
I2CStart();
I2CWrite(0x50<<1); //尋址器件,后續(xù)為寫操作
I2CWrite(addr); //寫入存儲地址
I2CWrite(dat); //寫入一個字節(jié)數(shù)據(jù)
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);//將數(shù)據(jù)存儲到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中斷服務(wù)函數(shù) */
void InterruptUART() interrupt 4
{
if (RI) //接收到字節(jié)
{
RI = 0; //手動清零接收中斷標(biāo)志位
RxdByte = SBUF; //接收到的數(shù)據(jù)保存到接收字節(jié)變量中
//用以提示用戶輸入的信息是否已正確接收
SBUF = RxdByte;
}
if (TI) //字節(jié)發(fā)送完畢
{
TI = 0; //手動清零發(fā)送中斷標(biāo)志位
}
}
復(fù)制代碼
作者:
八月初
時間:
2020-5-28 19:25
/* UART中斷服務(wù)函數(shù) */
void InterruptUART() interrupt 4
{
if (RI) //接收到字節(jié)
{
RI = 0; //手動清零接收中斷標(biāo)志位
RxdByte = SBUF; //接收到的數(shù)據(jù)保存到接收字節(jié)變量中
//用以提示用戶輸入的信息是否已正確接收
SBUF = RxdByte;
E2WriteByte(0x10,RxdByte);
}
if (TI) //字節(jié)發(fā)送完畢
{
TI = 0; //手動清零發(fā)送中斷標(biāo)志位
}
}
這樣子就可以了
作者:
f556
時間:
2020-5-29 10:13
細(xì)看了E2WriteByte在main中只調(diào)了一次。加在UART中解決了,無問題?
作者:
八月初
時間:
2020-6-1 21:57
f556 發(fā)表于 2020-5-29 10:13
細(xì)看了E2WriteByte在main中只調(diào)了一次。加在UART中解決了,無問題?
但是我加在中斷接收里面后,確實是可以達到我的題目要求了
作者:
樂兒翅
時間:
2020-7-13 19:31
加一個中斷 { if (RI) //接收到字節(jié) { RI = 0; //手動清零接收中斷標(biāo)志位 RxdByte = SBUF; //接收到的數(shù)據(jù)保存到接收字節(jié)變量中 //用以提示用戶輸入的信息是否已正確接收 SBUF = RxdByte; E2WriteByte(0x10,RxdByte);
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1