📄 main.c
字号:
//程序说明:
//该程序利用单片机完成数据在串口与SMBus总线(即I2C)之间的转发,即将串口接收
//到的数据通过I2C转发出去,将I2C接收到的数据通过串口转发出去
//
#include "c8051f310.h"
#define SYSCLK 24500000 // System clock frequency
#define SMB_FREQUENCY 50000 // Target SMBus frequency
#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command
// Device addresses (7 bits, lsb is a don't care)
#define F310_SLAVE 0xA0 // Device address for slave target
// Status vector - top 4 bits only
#define SMB_MTSTA 0xE0 // (MT) start transmitted
#define SMB_MTDB 0xC0 // (MT) data byte transmitted
#define SMB_MRDB 0x80 // (MR) data byte received
// End status vector definition
//-----------------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------------
unsigned char SMB_DATA_IN; // Global holder for SMBus data
// All receive data is written here
unsigned char SMB_DATA_OUT; // Global holder for SMBus data.
// All transmit data is read from here
unsigned char TARGET; // Target SMBus slave address
bit SMB_BUSY; // Software flag to indicate when the
// SMB_Read() or SMB_Write() functions
// have claimed the SMBus
bit SMB_RW; // Software flag to indicate the
// direction of the current transfer
/*SMBus地址*/
#define ADDR_SLAVE 0x10
#define ADDR_SLAVE_W 0x20
#define ADDR_SLAVE_R 0x21
#define ADDR_SELF 0x01
#define ADDR_SELF_W 0x02
#define ADDR_SELF_R 0x03
#define MAXBUFSIZE 50 //缓冲区大小
/*全局变量*/
unsigned char SMBus_Txchar; //存储SMBus口待发送的字节
unsigned char SMBus_TxCount = 0; //SMBus发送字节的计数
unsigned char xdata UARTRxBuf[MAXBUFSIZE]; //定义一个UART串口接收缓冲区
unsigned char UARTRxBuf_Front = -1; //UART串口缓冲区的头位置
unsigned char UARTRxBuf_Rear = -1; //UART串口缓冲区的尾位置
bit UART_Tx_Complete = 0; //指示UART发送一个字节完毕
unsigned char xdata SMBusRxBuf[MAXBUFSIZE]; //定义一个SMBus接收缓冲区
unsigned char SMBusRxBuf_Front = -1; //SMBus接收缓冲区头位置
unsigned char SMBusRxBuf_Rear = -1; //SMBus接收缓冲区尾位置
bit SMBus_Tx_Complete = 0; //指示SMBus发送一个字节完毕
/*函数原型声明*/
void SMBus_Tx(unsigned char ch);
void UART_Tx(unsigned char ch);
unsigned char ReadBuffer(unsigned char* Buffer,unsigned char* pFront,unsigned char* pRear);
unsigned char UartFrame_Complete=0;
unsigned int pRomAddr=0;
unsigned char xdata UartFrame[300];//,UartTxFrame[32];
int i=0;
int UartFrame_Num=0;
unsigned char temp_last='P';
int num=0;
sbit LED = P3^3;
unsigned char temp,t=0,IIC_Busy=0,RWByte=0,RxFlag=0,RxData=0x00,StopRequire=0;
int I2CRxNum=0;
// Peripheral specific initialization functions,
// Called from the Init_Device() function
void PCA_Init()
{
PCA0MD &= ~0x40;
PCA0MD = 0x00;
}
void Port_IO_Init()
{
XBR0 = 0x05;
XBR1 = 0x40;
/* P0MDIN = 0xFF; // All P0 pins digital input
P0MDOUT = 0x00; // All P0 pins open-drain output
P0 = 0xFF; */ //
}
/*
void Timer_Init()
{
TMOD = 0x22;//Mode2:8 bit Auto Reload
CKCON = 0x0C;//Timer0,1 use SYSCLK
TH0 = 0xF6;
TH1 = 0x2B;//Timer1 as UART Baud Triger, 0X2B~57600
TL1 = 0x2B;
TCON = 0x50;//Timer1,0 permission
}
*/
void Timer0_Init (void)
{
CKCON &= 0xF8; // Timer0 clock source = SYSCLK / 12
TMOD |= 0x02; // Timer0 in 8-bit auto-reload mode
TH0 = -(SYSCLK/SMB_FREQUENCY/12/3) ; // Timer0 configured to overflow at 1/3
// the rate defined by SMB_FREQUENCY
TL0 = -(SYSCLK/SMB_FREQUENCY/12/3); // Timer0 preloaded to overflow at the
// rate defined by SMB_FREQUENCY
TR0 = 1; // Timer0 enabled
/*
TCON = 0x50;
TMOD = 0x22;
CKCON = 0x0C;
TH0 = 0xF6;
TH1 = 0x61;
TL1 = 0x61;*/
}
void UART_Init()//use timer1
{
TMOD |= 0x20;//Mode2:8 bit Auto Reload
CKCON |= 0x08;//Timer1 use SYSCLK
//TH0 = 0xF6;
TH1 = 0x2B;//Timer1 as UART Baud Triger, 0X2B~57600
TL1 = 0x2B;
TCON |= 0x40;//Timer1 permission
SCON0 = 0x10;
}
void SMBus_Init()//use timer0
{
// SMB0CF = 0x80;
// SMB0CF = 0x5C; // Use Timer0 overflows as SMBus clock
// source
// Disable slave mode
// Enable setup & hold time extensions
// Enable SMBus Free timeout detect
// Enable SCL low timeout detect
SMB0CF |= 0x80; // Enable SMBus;
}
void Interrupts_Init()
{
EIE1 = 0x01;//SMBUS
IE = 0x10;//UART
}
// Initialization function for device,
// Call Init_Device() from your main program
void Init_Device(void)
{
PCA_Init();
OSCICN |=0x03;//SYSCLK取内部振荡器,不分频
Port_IO_Init();
Timer0_Init();
UART_Init();
SMBus_Init();
Interrupts_Init();
}
/*main()主函数*/
void main()
{
Init_Device(); //单片机初始化
IE = 0x90; //UART中断使能
//LED=0;
//LED=1;
EA=1;
// SBUF0=0X33;
// while(UART_Tx_Complete == 0);
// UART_Tx_Complete = 0;
//TI0 = 0;
// pRomAddr=UartFrame[2];//获取当前Rom地址
// while(SMB0CF & 0x20 != 0);//查询SMBus总线是否BUSY
// STA = 1; //发起一个I2C START
while(1)
{
if(UartFrame_Complete==1)
{
/* for(i=0;i<UartFrame_Num;i++)
{
SBUF0=UartFrame[i];
while(UART_Tx_Complete == 0);
UART_Tx_Complete = 0;
}*/
SBUF0='O';
while(UART_Tx_Complete == 0);
UART_Tx_Complete = 0;
SBUF0='K';
while(UART_Tx_Complete == 0);
UART_Tx_Complete = 0;
UartFrame_Complete=0;
// UartFrame_Num=0;
num=0;
//先写
RWByte=0xA0;//write
pRomAddr=UartFrame[2];//获取当前Rom地址
while(SMB0CF & 0x20 != 0);//查询SMBus总线是否BUSY
STA = 1; //发起一个I2C START
IIC_Busy=1;
while(IIC_Busy==1);
if(UartFrame[1]==0xA1)//写后的再读
{
RWByte=0xA1;//read
I2CRxNum=UartFrame[3]+1; //需要读的长度,0表示读1个
pRomAddr=UartFrame[2];//获取当前Rom地址
//pRomAddrEnd=pRomAddr+UartFrame[2]-1;
while(SMB0CF & 0x20 != 0);//查询SMBus总线是否BUSY
STA = 1; //发起一个I2C START
IIC_Busy=1;
// while(IIC_Busy==1);
}
}
if(RxFlag==1)
{
RxFlag=0;
SBUF0=RxData;
while(UART_Tx_Complete == 0);
UART_Tx_Complete = 0;
}
}
}
/*SMBus中断处理程序*/
void SMBus_Interrupt(void) interrupt 7
{
bit FAIL; // Used by the ISR to flag failed
// transfers
static bit ADDR_SEND; // Used by the ISR to flag byte
// transmissions as slave addresses
switch (SMB0CN & 0xF0) // Status vector
{
// Master Transmitter/Receiver: START condition transmitted.
case SMB_MTSTA:
//SMB0DAT = TARGET; // Load address of the target slave
//SMB0DAT |= SMB_RW; // Load R/W bit
//STA = 0; // Manually clear START bit
SMB0DAT =RWByte;//UartFrame[1] ; //发出从器件XFP地址以及R/W位
//SBUF0=UartFrame[1];
//while(UART_Tx_Complete == 0);
//UART_Tx_Complete = 0;
STA = 0;
i=1;
ADDR_SEND = 1;
break;
// Master Transmitter: Data byte transmitted
case SMB_MTDB:
if (ACK) // Slave ACK?
{
//if(UartFrame[1]==0xA1) //此次是读操作里面的写地址
// {
// SMB0DAT =UartFrame[2] ; //读Rom的地址
// StopRequire=1;
// STO=1; //写地址完毕
// // IIC_Busy=0;
// }
//else //是写操作
//{
i++;
if(RWByte==0xA0)//WRITE
{
if(((UartFrame[i]=='P')&&(i==UartFrame_Num))||(StopRequire==1))//stop
{
STO=1; //停止命令
// pRomAddr=pRomAddr+i-3;
IIC_Busy=0;
StopRequire=0;
}
else //send
{
SMB0DAT =UartFrame[i] ; //写Prom的地址或数据,发送
if(UartFrame[1]==0xA1) //此次是读操作里面的写地址
StopRequire=1;
////SBUF0=UartFrame[1];
//while(UART_Tx_Complete == 0);
// UART_Tx_Complete = 0;
}
}
else{} //do nothing
//}
/*
if (ADDR_SEND) // If the previous byte was a slave
{ // address,
ADDR_SEND = 0; // Next byte is not a slave address
if (SMB_RW==WRITE) // If this transfer is a WRITE,
{
SMB0DAT = SMB_DATA_OUT; // send data byte
}
else {} // If this transfer is a READ,
// proceed with transfer without
// writing to SMB0DAT (switch
// to receive mode)
}
else // If previous byte was not a slave
{ // address,
STO = 1; // set STO to terminte transfer
SMB_BUSY = 0; // and free SMBus interface
}*/
}
else // If slave NACK,
{
FAIL = 1; // Indicate failed transfer
// and handle at end of ISR
}
break;
// Master Receiver: byte received
case SMB_MRDB:
// UartTxFrame[i+1] =SMB0DAT; //发出从器件地址以及R/W位
RxData=SMB0DAT;
RxFlag=1;
// UartTxFrame[i]=pRomAddr;
pRomAddr++;
I2CRxNum--;
if((I2CRxNum!=0)&&(pRomAddr!=256)) //读页数据
//if((UartFrame[3]==0xFF)&&(pRomAddr!=256)) //读页数据
{
ACK=1;
i=i+2;
}
else
{
ACK=0; //给出传送完毕信息
//i=0;
STO=1; //停止
IIC_Busy=0;
}
//SMB_DATA_IN = SMB0DAT; // Store received byte
//SMB_BUSY = 0; // Free SMBus interface
//ACK = 0; // Send NACK to indicate last byte
// of this transfer
//STO = 1; // Send STOP to terminate transfer
break;
default:
FAIL = 1; // Indicate failed transfer
// and handle at end of ISR
break;
} // end switch
if (FAIL) // If the transfer failed,
{
SMB0CN &= ~0x40; // Reset communication
SMB0CN |= 0x40;
SMB_BUSY = 0; // Free SMBus
}
SI=0; // clear interrupt flag
}
/*UART中断处理程序*/
void UART_Interrupt(void) interrupt 4
{
/*如果串口接收到一个字节,将其写入串口缓冲区*/
if(RI0)
{
// LED=!LED;
temp=SBUF0;
t++;
// SBUF0=UartFrame[i];
// while(UART_Tx_Complete == 0);
// UART_Tx_Complete = 0;
if((temp=='S')&&(temp_last=='P')) //起始
{
num=0;
UartFrame[0]=temp;
}
else if(UartFrame[0]=='S')
UartFrame[num]=temp;
if((temp=='P')&&(UartFrame[0]=='S'))
{
// if(((UartFrame[1]==0xA0)&&(UartFrame[3]==num))||(UartFrame[1]==0xA1))//写操作需要长度信息。
{
// UartFrame_Complete=1;
if((num+1)>=5) //必须大于5个数据才算一组帧
{
UartFrame_Complete=1;
UartFrame_Num=num;//UartFrame_Num是这个包的数据个数
}
//else UartFrame[num]=temp;
}
}
num++;
temp_last=temp;
RI0=0;
}
/*如果串口发送完一个字节,将UART_Tx_Complete置1*/
else if(TI0)
{
UART_Tx_Complete = 1;
TI0 = 0;
}
}
/*SMBus发送字节程序*/
void SMBus_Tx(unsigned char ch)
{
while(SMB0CF & 0x20 != 0);//查询SMBus总线是否BUSY
SMBus_Txchar = ch;
SMBus_TxCount = 1;
STA = 1;
}
/*读缓冲区程序*/
unsigned char ReadBuffer(unsigned char* Buffer,unsigned char* pFront,unsigned char* pRear)
{
unsigned char ch;
*pFront = ((*pFront)+1) % MAXBUFSIZE;
ch = Buffer[*pFront];
return ch;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -