📄 25cl04.c
字号:
#include<c8051f000.h>
//OP_code command-----------
#define WREN 0x06
#define WRDI 0x04
#define RDSR 0x05
#define WRSR 0x01
#define READ 0x03
#define WRITE 0x02
#define WRITE1 0x00 // SMBus 写命令
#define READ1 0x01 // SMBus 读命令
#define CHIP_A 0xA0 // 芯片A 的器件地址
#define SMB_BUS_ERROR 0x00 // 对所有方式总线错误
#define SMB_START 0x08 // (MT & MR)起始条件已发送
#define SMB_RP_START 0x10 // (MT & MR)重复起始条件
#define SMB_MTADDACK 0x18 // (MT) 从地址+ W 已发送收到ACK
#define SMB_MTADDNACK 0x20 // (MT) 从地址+ W 已发送收到NACK
#define SMB_MTDBACK 0x28 // (MT) 数据字节已发送收到ACK
#define SMB_MTDBNACK 0x30 // (MT) 数据字节已发送收到NACK
#define SMB_MTARBLOST 0x38 // (MT) 竞争失败
#define SMB_MRADDACK 0x40 // (MR) 从地址+ R 已发送收到ACK
#define SMB_MRADDNACK 0x48 // (MR) 从地址+ W 已发送收到NACK
#define SMB_MRDBACK 0x50 // (MR) 收到数据字节ACK 已发送
#define SMB_MRDBNACK 0x58 // (MR) 收到数据字节NACK 已发送
sbit P1_6=P1^6;
sbit SPI_CS=P1^5;
bit mark;
//全局变量
//--------------------------------------------------------------------
char COMMAND; // 在SMBus 中断服务程序中用于
// 保存从地址+ R/W 位
char WORD; // 保持SMBus 要发送的数据字节
// 或刚收到的数据
char BYTE_NUMBER; // 在中用于检查发送的是什么数据
// 地址字节或数据字节
unsigned char ADDR; // EEPROM 存储器地址
bit SM_BUSY; // 该位在发送或接收开始时被置1 操作结束后由中断服务程序清0
unsigned char check=0x33;
unsigned char buffer1[10]=0;
unsigned char buffer2[10]=0;
void uart_init (void);
void read_data(unsigned addr_h,unsigned char addr_l,unsigned char *ptr,unsigned char num);
void write_data(unsigned addr_h,unsigned char addr_l,unsigned char *ptr,unsigned char num);
void SMBus_ISR (void);
void SM_Send (char chip_select, unsigned char byte_address, char out_byte);
char SM_Receive (char chip_select, unsigned char byte_address);
//main programme------------------------
void main (void)
{
unsigned int i,j=0;
WDTCN = 0xde; // 禁止看门狗定时器
WDTCN = 0xad;
OSCICN|=0x03;
XBR0=0x87; // CP0O UART SPI0 SMB0
XBR1=0x04; //INT0
XBR2=0x40;
PRT0CF=0xB5;
PRT1CF=0xff;
PRT2CF=0xf7;
SMB0CN = 0x44; // 允许SMBus 在应答周期发送ACK
SMB0CR = -80; // SMBus 时钟频率= 100kHz.
EIP1=0x00;
SM_BUSY = 0; // 为第一次传输释放SMBus
EIE1 |= 0x02; // SMBus中断允许
//SPI config
SPI0CFG = 0x07;
SPI0CN = 0x03;
SPI0CKR= 0; //---------1M SCK
IP=0X00;
IE=0X00;
uart_init();
EA=1; //开中断
// EX0=1;
WDTCN=0XA5;
EMI0CN=0;
CPT0CN|=0x81;//cp0en---1 4.5mv 负向回差电压
TCON|=0x01;
REF0CN=0x07;
mark=0;
while(1)
{
// IIC:
//if(mark)
{
// SM_Send(CHIP_A, 0x88, 0x58+j++); //发送0x53 数据到CHIP_A 的地址0x88
//EX0=0;
}
//else
{
//P1_6=!P1_6;
/* write_data(0x05,0x55,buffer2,6);
read_data(0x00,0x01,buffer1,8);*/
SM_Send(CHIP_A, 0x88, 0x53); //发送0x53 数据到CHIP_A 的地址0x88
//check=0;
check = SM_Receive(CHIP_A, 0x88); // 读CHIP_A 的地址0x88
if(check==0x53)
P1_6=!P1_6;
for(i=0;i<6;i++)for(i=0;i<55536;i++);
/*SBUF=check;
while(TI==0);TI=0;
if(RI)
{ check=SBUF+1;RI=0;}*/
}
}
}
void read_data(unsigned addr_h,unsigned char addr_l,unsigned char *ptr,unsigned char num)
{
unsigned char i;
SPI_CS=1;
SPI_CS=0;
SPI0DAT = READ;while(SPIF==0);SPIF=0;
SPI0DAT = addr_h;while(SPIF==0);SPIF=0;
SPI0DAT = addr_l;while(SPIF==0);SPIF=0;
for(i=0;i<num;i++)
{
SPI0DAT = 0x00;while(SPIF==0);*(ptr+i)=SPI0DAT;SPIF=0;
}
SPI_CS=1;
}
void write_data(unsigned addr_h,unsigned char addr_l,unsigned char *ptr,unsigned char num)
{
unsigned char i;
SPI_CS=1;
SPI_CS=0;
SPI0DAT=WREN; while(SPIF==0);SPIF=0;
SPI0DAT=WRITE; while(SPIF==0);SPIF=0;
SPI0DAT=addr_h; while(SPIF==0);SPIF=0;
SPI0DAT=addr_l; while(SPIF==0);SPIF=0;
for(i=0;i<num;i++)
{
SPI0DAT=*(ptr+i); while(SPIF==0);SPIF=0;
}
SPI0DAT=WRDI; while(SPIF==0);SPIF=0;
SPI_CS=1;
}
void uart_init (void)
{
SCON = 0x50; // SCON 方式1 8位UART 允许RX
TMOD = 0x20; // TMOD 定时器1 方式2 8bit 重装载
TH1 = -1;
TL1 = -6;
TR1 = 1; // 启动定时器1
CKCON |= 0x10; // 定时器1使用sysclk 作为时基
PCON |= 0x80; // SMOD = 1
TI = 1; // 指示TX 准备好
}
/*
void INT0process(void) interrupt 0 using 1
{
IE0=0;
EX0=0;
mark=1;
//goto IIC;
// P1_6=!P1_6;
// 测试代码-------------------------------------------------------------
//SM_Send(CHIP_A, 0x88, 0x53+5+6); //发送0x53 数据到CHIP_A 的地址0x88
write_data(0x05,0x55,buffer2,6);
}
*/
// SMBus 字节写函数-----------------------------------------------------
// 向给定存储器地址写一个字节
// out_byte = 待写数据
// byte_address = 待写存储器地址
// chip_select = 待写EEPROM 芯片的器件地址
void SM_Send (char chip_select, unsigned char byte_address, char out_byte)
{
while (SM_BUSY); // 等待SMBus 空闲
SM_BUSY = 1; // 占用SMBus 设置为忙
SMB0CN = 0x44; // SMBus 允许应答周期发ACK
BYTE_NUMBER = 1; // 地址字节
COMMAND = (chip_select | WRITE1); // 片选+ WRITE
ADDR = byte_address;
WORD = out_byte; // 待写数据
STA = 1; // 启动传输过程
}
// SMBus 随机读函数-----------------------------------------------------
// 从给定存储器地址读一个字节
// byte_address = 要读取的存储器地址
// chip_select = 待读EEPROM 的器件地址
char SM_Receive(char chip_select, unsigned char byte_address)
{
while (SM_BUSY); // 等待总线空闲
SM_BUSY = 1; //占用SMBus 设置为忙
SMB0CN = 0x44; // 允许SMBus 应答周期发ACK
BYTE_NUMBER = 1; // 1地址字节
COMMAND = (chip_select | READ1); // 片选+ READ
ADDR = byte_address ; //8 位地址
STA = 1; // 启动传输过程
while (SM_BUSY); // 等待传输结束
return WORD;
}
//--------------------------------------------------------------------
// 中断服务程序
//--------------------------------------------------------------------
// SMBus 中断服务程序
void SMBUS_ISR (void) interrupt 7 using 1
{
switch (SMB0STA){ // SMBus状态码SMB0STA 寄存器
// 主发送器/接收器起始条件已发送
// 在该状态发送的COMMAND 字的R/W 位总是为0(W)
// 因为对于读和写操作来说都必须先写存储器地址
case SMB_START:
SMB0DAT = (COMMAND & 0xFE); // 装入要访问的从器件的地址
STA = 0; // 手动清除START 位
break;
//主发送器/接收器重复起始条件已发送
// 该状态只应在读操作期间出现在存储器地址已发送并得到确认之后
case SMB_RP_START:
SMB0DAT = COMMAND; // COMMAND 中应保持从地址+ R.
STA = 0;
break;
// 主发送器从地址+ WRITE 已发送收到ACK
case SMB_MTADDACK:
SMB0DAT = ADDR; // 装入待写存储器地址的高字节
break;
// 主发送器从地址+ WRITE 已发送收到NACK
// 从器件不应答发送STOP + START 重试
case SMB_MTADDNACK:
STO = 1;
STA = 1;
break;
// 主发送器数据字节已发送收到ACK
// 该状态在写和读操作中都要用到BYTE_NUMBER 看存储器地址状态– 如果
// 只发送了HIGH_ADD 则装入LOW_ADD 如果LOW_ADD 已发送检查COMMAND
// 中的R/W 值以决定下一状态
case SMB_MTDBACK:
switch (BYTE_NUMBER){
case 1: // 如果BYTE_NUMBER=1 ADDR 已发送
if (COMMAND & 0x01) // 如果R/W=READ 发送重复起始条件
STA = 1;
else{
SMB0DAT = WORD; // 如果R/W=WRITE 装入待写字节
BYTE_NUMBER--;}
break;
default: // 如果BYTE_NUMBER=0 传输结束
STO = 1;
SM_BUSY = 0; // 释放SMBus
}
break;
// 主发送器数据字节已发送收到NACK
// 从器件不应答发送STOP + START 重试
case SMB_MTDBNACK:
STO = 1;
STA = 1;
break;
// 主发送器竞争失败
// 不应出现如果出现重新开始传输过程
case SMB_MTARBLOST:
STO = 1;
STA = 1;
break;
// 主接收器从地址+ READ 已发送收到ACK
// 设置为在下一次传输后发送NACK 因为那将是最后一个字节唯一
case SMB_MRADDACK:
AA = 0; // 在应答周期NACK
break;
// 主接收器从地址+ READ 已发送收到NACK
// 从器件不应答发送重复起始条件重试
case SMB_MRADDNACK:
STA = 1;
break;
// 收到数据字节ACK 已发送
// 该状态不应出现因为AA 已在前一状态被清0 如果出现发送停止条件
case SMB_MRDBACK:
STO = 1;
SM_BUSY = 0;
break;
// 收到数据字节NACK 已发送
// 读操作已完成读数据寄存器后发送停止条件
case SMB_MRDBNACK:
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0; // 释放SMBus
break;
// 在本应用中所有其它状态码没有意义通信复位
default:
STO = 1; // 通信复位
SM_BUSY = 0;
break;
}
SI=0; // 清除中断标志
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -