📄 smbus_master_f33x.c
字号:
//-----------------------------------------------------------------------------
//
// 文件名:SMBus_Master_F33x.c
//
// 编写人:JS
//
// 编写时间:2004/1/3
//
// 目标器件: C8051F33x
//
// 编译工具: Silicon Laboratories IDE
//
//-----------------------------------------------------------------------------
//程序描述:
// C8051F330作为主器件,C8051F310作为从器件,定时器1为I2C时钟源,定时器3为SCL低电平超时检测,
//此程序为单字节收发.收发数据可以由用户自己定义。
//-----------------------------------------------------------------------------
//头文件包含
//-----------------------------------------------------------------------------
#include <c8051f330.h>
//-----------------------------------------------------------------------------
//常量定义
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // 系统工作频率
#define SMB_FREQUENCY 50000 // SCL时钟
#define WRITE 0x00 // SMBus 写命令
#define READ 0x01 // SMBus 读命令
//-----------------------------------------------------------------------------
// 设备地址 (高7位)
//-----------------------------------------------------------------------------
#define F310_SLAVE 0xf0 // 从机设备地址
//-----------------------------------------------------------------------------
// 状态向量(只有高4位)
//-----------------------------------------------------------------------------
#define SMB_MTSTA 0xE0 // 准备发送
#define SMB_MTDB 0xC0 // 发送数据字节
#define SMB_MRDB 0x80 // 接收数据字节
//-----------------------------------------------------------------------------------
//全局变量定义
//----------------------------------------------------------------------------------
unsigned char SMB_DATA_IN; // 接收缓冲字节
unsigned char SMB_DATA_OUT; // 发送缓冲字节
unsigned char TARGET; // 从机地址
bit SMB_BUSY; // 读写忙标志位
bit SMB_RW; // 读写标志位
sbit LED = P1^3; // LED在P3.3口
//-----------------------------------------------------------------------------
//定时器3特殊功能寄存器定义
//-----------------------------------------------------------------------------
sfr16 TMR3RL = 0x92;
sfr16 TMR3 = 0x94;
//------------------------------------------------------------------------------------
// 函数定义
//------------------------------------------------------------------------------------
void SMBus_Init (void);
void Timer1_Init (void);
void Timer3_Init (void);
void Port_Init (void);
void SMBus_ISR (void);
void Timer3_ISR (void);
void SMB_Write (void);
void SMB_Read (void);
//------------------------------------------------------------------------------------
// 主程序
//------------------------------------------------------------------------------------
void main (void)
{
unsigned char i, error;
PCA0MD &= ~0x40; // 禁止看门狗
OSCICN |= 0x03; // 使用内部振荡器(24500000)
Port_Init (); // 内部交叉开关及I/O初始化
Timer1_Init (); // 定时器1初始化,作为SMBus的时钟源
Timer3_Init (); // 定时器3初始化,作为SMBus SCL信号低电平
// 超时检测
SMBus_Init (); // 初始化并使能SMBus
EIE1 |= 1; // SMBus 中断使能
IE |= 0x20; // 定时器2中断使能
EA = 1; // 总中断使能
//------------------------初始化结束----------------------------------------
i = 0; // 数据发送计数
error = 0; // 通讯失败计数
LED = 0; // 关闭LED
while (1)
{
for (i=0;i<255;i++)
{
SMB_DATA_OUT = i; // 定义要发送的数据
TARGET = F310_SLAVE; // 从机地址
SMB_Write();
TARGET = F310_SLAVE;
SMB_Write();
if(SMB_DATA_IN != SMB_DATA_OUT)
error++;
LED = (!LED); // LED 状态取反
}
}
}
//------------------------------------------------------------------------------------
// SMBus发送程序
//------------------------------------------------------------------------------------
void SMB_Write (void)
{
while (SMB_BUSY);
SMB_BUSY = 1;
SMB_RW = 0;
STA = 1;
}
//------------------------------------------------------------------------------------
// SMBus接收程序
//------------------------------------------------------------------------------------
void SMB_Read (void)
{
while (SMB_BUSY);
SMB_BUSY = 1;
SMB_RW = 1;
STA = 1;
while (SMB_BUSY);
}
//------------------------------------------------------------------------------------
// SMBus初始化
//------------------------------------------------------------------------------------
void SMBus_Init (void)
{
SMB0CF = 0x5D;
SMB0CF |= 0x80;
}
//------------------------------------------------------------------------------------
// 定时器3初始化程序
//------------------------------------------------------------------------------------
void Timer3_Init (void)
{
TMR3CN = 0x00; // 定时器3工作在16位自动重装入方式
TMR3 = -(SYSCLK/12/40); // 定时器3配制为25ms溢出
TMR3RL = -(SYSCLK/12/40);
CKCON &= ~0x40; // 定时器3时钟源=SYSCLK/12
TMR3 |= 0x04; // 使能定时器3
}
//------------------------------------------------------------------------------------
// 定时器1初始化
//------------------------------------------------------------------------------------
void Timer1_Init (void)
{
CKCON &= ~0x0B; // 定时器1时钟源 = SYSCLK / 12
TMOD = 0x20; // 定时器1工作在8位自动重装入方式
TH1 = -(SYSCLK/SMB_FREQUENCY/12/3);
TL1 = -(SYSCLK/SMB_FREQUENCY/12/3);
TR1 = 1; // 定时器1使能
}
//-----------------------------------------------------------------------------------
// I/O口初始化
//-----------------------------------------------------------------------------------
void Port_Init (void)
{
XBR0 = 0x04; // SMBus 分配到P0.0、P0.1
XBR1 = 0x40;
P0MDIN = 0xFF;
P0MDOUT = 0x00;
P1MDOUT = 0xff;
}
//------------------------------------------------------------------------------------
// SMBus中断服务程序
//------------------------------------------------------------------------------------
void SMBus_ISR (void) interrupt 7
{
bit FAIL; // 通讯失败标志位
bit ADDR_SEND; // 发送从机地址标志位
switch (SMB0CN & 0xF0) // 状态向量
{
case SMB_MTSTA:
SMB0DAT = TARGET;
SMB0DAT |= SMB_RW; // 装入从机地址和读写位
STA = 0; // 清发送位
ADDR_SEND = 1; //此时发送的是从机地址和读写位,置标志位为1
break;
//----------------------------------------------------------------------------
// 主机发送:数据发送
case SMB_MTDB:
if (ACK) // 从机应答信号?
{
if (ADDR_SEND) // 前一次发送的是否是从机地址
{
ADDR_SEND = 0; // 如是从机地址,下一次将不再发送从机地址
if (SMB_RW==WRITE) // 前一次发送的命令是读还是写
{
SMB0DAT = SMB_DATA_OUT; // 前一次发送的命令如果是写,就装入要发送的数据
}
else {} // 如果这个命令是读, 程序将不会写SMB0DAT
// (切换到接收模式)
}
else // 前一次发送的不是从机地址
{
STO = 1; // 置停止位为1
SMB_BUSY = 0; // 设置SMBus总线空闲
}
}
else // 如果接收到的是非应答信号,
{
FAIL = 1; // 就设置失败标志位,并退出中断
}
break;
// 主机接收:单字节接收
case SMB_MRDB:
SMB_DATA_IN = SMB0DAT; // 保存接收字节
SMB_BUSY = 0; // 设置SMBus总线空闲
ACK = 0; // 发送应答信号
STO = 1; // 发送停止位
break;
default:
FAIL = 1;
break;
}
if (FAIL) // 是否有通讯失败,
{
SMB0CN &= ~0x40; // 复位总线
SMB0CN |= 0x40;
SMB_BUSY = 0; // SMBus 总线空闲
}
SI=0; // 清SMBus中断为标志位
}
//-----------------------------------------------------------------------------------
// 定时器3中断服务程序
//-----------------------------------------------------------------------------------
//
//定时器3中断表示SMBus总线的SCL位号低电平超时
// 这里将禁止和重新使能SMBus总线
//
void Timer3_ISR (void) interrupt 14
{
SMB0CN &= ~0x40; // 禁止SMBus
SMB0CN |= 0x40; // 重新使能SMBus
TMR3CN &= ~0x80; // 清定时器3中断标志位
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -