📄 eep_040.c
字号:
/****************************************************************************
在主程序中有标识设断点的地方,可观察向铁电存储器写入和读取数据的情况
****************************************************************************/
#include "C8051F040.h"
#define uchar unsigned char
#define uint unsigned int
#define WRITE 0x00 // WRITE direction bit
#define READ 0x01 // READ direction bit
#define CHIP_A 0xA0 // Device address for chip A
#define SMB_BUS_ERROR 0x00 // (all modes) BUS ERROR
#define SMB_START 0x08 // (MT & MR) START transmitted
#define SMB_RP_START 0x10 // (MT & MR) repeated START
#define SMB_MTADDACK 0x18 // (MT) Slave address + W transmitted;
// ACK received
#define SMB_MTADDNACK 0x20 // (MT) Slave address + W transmitted;
// NACK received
#define SMB_MTDBACK 0x28 // (MT) data byte transmitted; ACK rec'vd
#define SMB_MTDBNACK 0x30 // (MT) data byte transmitted; NACK rec'vd
#define SMB_MTARBLOST 0x38 // (MT) arbitration lost
#define SMB_MRADDACK 0x40 // (MR) Slave address + R transmitted;
// ACK received
#define SMB_MRADDNACK 0x48 // (MR) Slave address + R transmitted;
// NACK received
#define SMB_MRDBACK 0x50 // (MR) data byte rec'vd; ACK transmitted
#define SMB_MRDBNACK 0x58 // (MR) data byte rec'vd; NACK transmitted
uchar COMMAND; // Holds the slave address + R/W bit for
// use in the SMBus ISR.
uchar WORD; // Holds data to be transmitted by the SMBus
// OR data that has just been received.
uchar BYTE_NUMBER; // Used by ISR to check what data has just been
// sent - High address byte, Low byte, or data
// byte
uchar HIGH_ADD, LOW_ADD; // High & Low byte for EEPROM memory address
bit SM_BUSY;
void SMBus_ISR (void);
void SM_Send (uchar chip_select, uchar byte_address, uchar out_byte);
char SM_Receive (uchar chip_select, uchar byte_address);
void os_init();
void port_init();
void smbus_init();
void spi_init();
void uart_init();
void main()
{
uchar check;
WDTCN = 0xDE; // 关闭看门狗
WDTCN = 0xAD;
EIE1 = 0x02;
EA=1;
os_init();
port_init();
spi_init();
uart_init();
smbus_init();
SM_BUSY=0;
while(1)
{
SM_Send(CHIP_A, 0x01, 0x55); // Send 0x53(data) to address 0x88 on CHIP_A
check = SM_Receive(CHIP_A, 0x01); // 在此处设断点可观察check值的变化
}
}
void os_init()
{
int i = 0;
SFRPAGE = CONFIG_PAGE;
OSCXCN = 0x67;
for (i = 0; i < 256; i++); // Wait 1ms for initialization
while ((OSCXCN & 0x80) == 0);
CLKSEL = 0x01;
}
void port_init()
{
SFRPAGE = CONFIG_PAGE;
XBR0 = 0x0f;
XBR2 = 0x40;
}
void spi_init()
{
SFRPAGE = SPI0_PAGE;
SPI0CFG = 0x40;
SPI0CN = 0x01;
SPI0CKR = 0x6D;
}
void uart_init()
{
SFRPAGE = UART0_PAGE;
SCON0 = 0x50; //允许uart1
}
void smbus_init()
{
SFRPAGE = SMB0_PAGE;
SMB0CN = 0x40; //允许SMbus
SMB0CR = 0x99; //系统时钟为100KHZ
}
void SM_Send (uchar chip_select, uchar byte_address, uchar out_byte)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SFRPAGE = SMB0_PAGE;
SMB0CN = 0x44; // SMBus enabled,
// ACK on acknowledge cycle
BYTE_NUMBER = 2; // 2 address bytes.
COMMAND = (chip_select | WRITE); // Chip select + WRITE
LOW_ADD = (byte_address & 0xFF); // Lower 8 address bits
WORD = out_byte; // Data to be writen
SFRPAGE = SMB0_PAGE;
STO = 0;
STA = 1; // Start transfer
}
// SMBus random read function------------------------------------------------------
// Reads 1 byte from the specified memory location.
//
// byte_address = memory address of byte to read
// chip_select = device address of EEPROM to be read from
char SM_Receive (uchar chip_select, uchar byte_address)
{
while (SM_BUSY); // Wait for bus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SFRPAGE = SMB0_PAGE;
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 2; // 2 address bytes
COMMAND = (chip_select | READ); // Chip select + READ
LOW_ADD = (byte_address & 0xFF); // Lower 8 address bits
SFRPAGE = SMB0_PAGE;
STO = 0;
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
return WORD;
}
//------------------------------------------------------------------------------------
// Interrupt Service Routine
//------------------------------------------------------------------------------------
// SMBus interrupt service routine:
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA){ // Status code for the SMBus (SMB0STA register)
// Master Transmitter/Receiver: START condition transmitted.
// The R/W bit of the COMMAND word sent after this state will
// always be a zero (W) because for both read and write,
// the memory address must be written first.
case SMB_START:
SFRPAGE = SMB0_PAGE;
SMB0DAT = (COMMAND & 0xFE); // Load address of the slave to be accessed.
STA = 0; // Manually clear START bit
break;
// Master Transmitter/Receiver: Repeated START condition transmitted.
// This state should only occur during a read, after the memory address has been
// sent and acknowledged.
case SMB_RP_START:
SFRPAGE = SMB0_PAGE;
SMB0DAT = COMMAND; // COMMAND should hold slave address + R.
STA = 0;
break;
// Master Transmitter: Slave address + WRITE transmitted. ACK received.
// case SMB_MTADDACK:
// SFRPAGE = SMB0_PAGE;
// SMB0DAT = LOW_ADD; // Load high byte of memory address
// to be written.
// break;
// Master Transmitter: Slave address + WRITE transmitted. NACK received.
// The slave is not responding. Send a STOP followed by a START to try again.
case SMB_MTADDNACK:
SFRPAGE = SMB0_PAGE;
STO = 1;
STA = 1;
break;
// Master Transmitter: Data byte transmitted. ACK received.
// This state is used in both READ and WRITE operations. Check BYTE_NUMBER
// for memory address status - if only HIGH_ADD has been sent, load LOW_ADD.
// If LOW_ADD has been sent, check COMMAND for R/W value to determine
// next state.
case SMB_MTDBACK:
switch (BYTE_NUMBER){
case 2: // If BYTE_NUMBER=2, only HIGH_ADD
SMB0DAT = LOW_ADD; // has been sent.
BYTE_NUMBER--; // Decrement for next time around.
break;
case 1: // If BYTE_NUMBER=1, LOW_ADD was just sent.
if (COMMAND & 0x01){ // If R/W=READ, sent repeated START.
SFRPAGE = SMB0_PAGE;
STO = 0;
STA = 1;
} else {
SFRPAGE = SMB0_PAGE;
SMB0DAT = WORD; // If R/W=WRITE, load byte to write.
BYTE_NUMBER--;
}
break;
default: // If BYTE_NUMBER=0, transfer is finished.
SFRPAGE = SMB0_PAGE;
STO = 1;
SM_BUSY = 0; // Free SMBus
}
break;
// Master Transmitter: Data byte transmitted. NACK received.
// Slave not responding. Send STOP followed by START to try again.
case SMB_MTDBNACK:
SFRPAGE = SMB0_PAGE;
STO = 1;
STA = 1;
break;
// Master Transmitter: Arbitration lost.
// Should not occur. If so, restart transfer.
case SMB_MTARBLOST:
SFRPAGE = SMB0_PAGE;
STO = 1;
STA = 1;
break;
// Master Receiver: Slave address + READ transmitted. ACK received.
// Set to transmit NACK after next transfer since it will be the last (only)
// byte.
case SMB_MRADDACK:
SFRPAGE = SMB0_PAGE;
AA = 0; // NACK sent on acknowledge cycle.
break;
// Master Receiver: Slave address + READ transmitted. NACK received.
// Slave not responding. Send repeated start to try again.
case SMB_MRADDNACK:
SFRPAGE = SMB0_PAGE;
STO = 0;
STA = 1;
break;
// Data byte received. ACK transmitted.
// State should not occur because AA is set to zero in previous state.
// Send STOP if state does occur.
case SMB_MRDBACK:
SFRPAGE = SMB0_PAGE;
STO = 1;
SM_BUSY = 0;
break;
// Data byte received. NACK transmitted.
// Read operation has completed. Read data register and send STOP.
case SMB_MRDBNACK:
SFRPAGE = SMB0_PAGE;
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0; // Free SMBus
break;
// All other status codes meaningless in this application. Reset communication.
default:
SFRPAGE = SMB0_PAGE;
STO = 1; // Reset communication.
SM_BUSY = 0;
break;
}
SI=0; // clear interrupt flag
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -