C8051F I2C(SMBus)程序

2020-06-29来源: eefocus关键字:C8051F  I2C  SMBus

/********************************************************************************************************
*
* File : ws_iic_port.h
* Hardware Environment: 
* Build Environment : Silicon LABs 3.42.00 / uVision3 V3.80 20100913
* Version : 
* By : Su Wei Feng
*
*(c) Copyright 2005-2010, WaveShare
*http://www.waveshare.net
*All Rights Reserved
*
*********************************************************************************************************/

#ifndef _WS_IIC_PORT_H_
#define _WS_IIC_PORT_H_

#define SMB_FREQUENCY 100000 // Target SCL clock rate
// This example supports in 100kHz
void SMBus_Init(void);
void Check_SDA(void);
void SMBus_Write(uint wrDAdr,uchar Data1,uchar Data2,uchar Num);
void SMBus_Read(uint wrDAdr,uchar *Data,uchar Num);

/*Hardware Environment:DVK501 && F320+ EX*/
#if defined(_DVK501_F320_EX_)

void Timer1_Init(void);
void Timer3_Init(void);
void Enb_Interrupt(void);
void SMBus_ISR(void);
void Timer3_ISR(void);

// 16-bit SFR declarations
sfr16 TMR3RL = 0x92; // Timer3 reload registers
sfr16 TMR3 = 0x94; // Timer3 counter registers

sbit SDA = P1^0; // SMBus on P1.0
sbit SCL = P1^1; // and P1.1

void SMBus_Init(void) 
{
XBR0 |= 0x07; // Enable SMBus pins
P1MDOUT = 0x00; // All P1 pins open-drain output
P1 = 0xFF;
SMB0CF = 0x5D; // Use Timer1 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 
Timer1_Init();
Timer3_Init();
}


void Timer1_Init(void)
{
// Make sure the Timer can produce the appropriate frequency in 8-bit mode
// Supported SMBus Frequencies range from 10kHz to 100kHz. The CKCON register
// settings may need to change for frequencies outside this range.
#if ((SYSCLK/SMB_FREQUENCY/3) < 255)
#define SCALE 1
CKCON |= 0x08; // Timer1 clock source = SYSCLK
#elif ((SYSCLK/SMB_FREQUENCY/4/3) < 255)
#define SCALE 4
CKCON |= 0x01;
CKCON &= ~0x0A; // Timer1 clock source = SYSCLK / 4
#endif

TMOD = 0x20; // Timer1 in 8-bit auto-reload mode

// Timer1 configured to overflow at 1/3 the rate defined by SMB_FREQUENCY
TH1 = -(SYSCLK/SMB_FREQUENCY/SCALE/3);
TL1 = TH1; // Init Timer1
TR1 = 1; // Timer1 enabled
}


void Timer3_Init(void)
{
TMR3CN = 0x00; // Timer3 configured for 16-bit auto-
// reload, low-byte interrupt disabled

CKCON &= ~0x40; // Timer3 uses SYSCLK/12
TMR3RL = -(SYSCLK/12/40); // Timer3 configured to overflow after
TMR3 = TMR3RL; // ~25ms (for SMBus low timeout detect):
// 1/.025 = 40

EIE1 |= 0x80; // Timer3 interrupt enable
TMR3CN |= 0x04; // Start Timer3
}


void Enb_Interrupt(void)
{
EIE1 |= 0x01; // Enable the SMBus interrupt
EA = 1; // Global interrupt enable
}


#else
#warning "iic interface undefined."
#endif

#include <../../../../library/C8051F/ws_iic.h>

#endif /*_WS_IIC_PORT_H_*/

 

/********************************************************************************************************
*
* File : ws_iic.h
* Hardware Environment: 
* Build Environment : Silicon LABs 3.42.00 / uVision3 V3.80 20100913
* Version : 
* By : Su Wei Feng
*
*(c) Copyright 2005-2010, WaveShare
*http://www.waveshare.net
*All Rights Reserved
*
*********************************************************************************************************/

#ifndef _WS_IIC_H_
#define _WS_IIC_H_

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command

// Status vector - top 4 bits only
#define SMBus_MTSTA 0xE0 // (MT) start transmitted
#define SMBus_MTDB 0xC0 // (MT) data byte transmitted
#define SMBus_MRDB 0x80 // (MR) data byte received
// End status vector definition

//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
unsigned char SMBus_DATA_IN[3]; // Global holder for SMBus data
// All receive data is written here

unsigned char SMBus_DATA_OUT[2]; // Global holder for SMBus data.
// All transmit data is read from here

unsigned char COMMAND,num[2]; // Target SMBus slave address

bit SMBus_BUSY; // Software flag to indicate when the
// SMB_Read() or SMB_Write() functions
// have claimed the SMBus
bit SMBus_WR; // SMBus READ or WRITE, 0 is READ, 1 is WRITE

//-----------------------------------------------------------------------------
// Check_SDA
//-----------------------------------------------------------------------------
// If slave is holding SDA low because of an improper SMBus reset or error
void Check_SDA(void)

uchar i; // Dummy variable counters
while(!SDA)
{
// Provide clock pulses to allow the slave to advance out
// of its current state. This will allow it to release SDA.
XBR1 = 0x40; // Enable Crossbar
SCL = 0; // Drive the clock low
for(i = 0; i < 255; i++); // Hold the clock low
SCL = 1; // Release the clock
while(!SCL); // Wait for open-drain
// clock output to rise
for(i = 0; i < 10; i++); // Hold the clock high
XBR1 = 0x00; // Disable Crossbar
}
}

//-----------------------------------------------------------------------------
// wrDAdr:I2C address
// dat:I2C data
//-----------------------------------------------------------------------------
void SMBus_Write(uint wrDAdr,uchar Data1,uchar Data2,uchar Num)
{
while(SMBus_BUSY); // Wait for SMBus to be free.
SMBus_BUSY = 1; // Claim SMBus (set to busy)
COMMAND = wrDAdr; 
SMBus_DATA_OUT[0] = Data1;
SMBus_DATA_OUT[1] = Data2;
num[0] = Num;
SMBus_WR = 0;
STO = 0;
STA = 1; // Start transfer
while(SMBus_BUSY); // Wait for SMBus to be free.
}

//-----------------------------------------------------------------------------
// wrDAdr:I2C address
//-----------------------------------------------------------------------------
void SMBus_Read(uint wrDAdr,uchar *Data,uchar Num)
{
uchar i;
while(SMBus_BUSY); // Wait for bus to be free.
SMBus_BUSY = 1; // Claim SMBus (set to busy)
COMMAND = wrDAdr;
num[1] = Num;
SMBus_WR = 1;
STO = 0;
STA = 1; // Start transfer 
while(SMBus_BUSY); // Wait for transfer to complete
for(i=0;iData[i] = SMBus_DATA_IN[i];
}


void SMBus_ISR(void) interrupt 7
{
bit FAIL = 0; // Used by the ISR to flag failed transfers
static uchar sent_byte_counter,rec_byte_counter;

if (ARBLOST == 0) // Check for errors
{
// Normal operation
switch (SMB0CN & 0xF0) // Status vector
{
// Master Transmitter/Receiver: START condition transmitted.
case SMBus_MTSTA:
{
SMB0DAT = COMMAND; // Load address of the target slave
STA = 0; // Manually clear START bit
sent_byte_counter = 1;
rec_byte_counter = 1; 
break;
}
// Master Transmitter: Data byte transmitted
case SMBus_MTDB:
{
if (ACK) // Slave ACK?
{
if (SMBus_WR == WRITE) // If this transfer is a WRITE,
{
if (sent_byte_counter <= num[0])
{
// send data byte
SMB0DAT = SMBus_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
}
else
{
STO = 1; // Set STO to terminate transfer
SMBus_BUSY = 0; // And free SMBus interface
}
}
}
else // If slave NACK,
{
STO = 1; // Send STOP condition, followed
STA = 1; // By a START
}
break;
}
// Master Receiver: byte received
case SMBus_MRDB:

if (rec_byte_counter < num[1])
{
SMBus_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
ACK = 1; // Send ACK to indicate byte received
rec_byte_counter++; // Increment the byte counter
}
else
{
SMBus_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
SMBus_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
}
else
{
// ARBLOST = 1, error occurred... abort transmission
FAIL = 1;
} // end ARBLOST if

if (FAIL) // If the transfer failed,
{
SMB0CF &= ~0x80; // Reset communication
SMB0CF |= 0x80;
STA = 0;
STO = 0;
ACK = 0;

SMBus_BUSY = 0; // Free SMBus
}

SI = 0; // Clear interrupt flag
}


void Timer3_ISR(void) interrupt 14
{
SMB0CF &= ~0x80; // Disable SMBus
SMB0CF |= 0x80; // Re-enable SMBus
TMR3CN &= ~0x80; // Clear Timer3 interrupt-pending flag
STA = 0;
SMBus_BUSY = 0; // Free SMBus
}

#endif /*_WS_IIC_H_*/

关键字:C8051F  I2C  SMBus 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic501482.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:使用PCF8574扩展C8051F的I/O端口
下一篇:使用74LS165将C8051F的串口输入扩为并口输入

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

C8051F烧写程序快速入门(Keil)
注:下载程序必须先安装Keil软件,以及对应的Silicon IDE驱动软件·Keil的安装  请到 Keil 官方网站: https://www.keil.com/c51/demo/eval/c51.htm下载安装。·Keil μVision Driver 的安装  请到 Silabs 官方网站: http://www.silabs.com/products/mcu/Pages/KeilDriver.aspx下载安装。1、安装好Keil μVision Driver驱动并且设置好下载程序前的相关配置(点击查看)2、如下图所示,点击菜单栏中的"Debug -> Start/Stop Debug Session
发表于 2020-06-30
<font color='red'>C8051F</font>烧写程序快速入门(Keil)
C8051F仿真调试快速入门(Silicon IDE)
注:下载程序必须首先安装Silicon IDE以及Keil软件·Keil的安装  请到 Keil 官方网站: https://www.keil.com/c51/demo/eval/c51.htm下载安装。·Silicon IDE的安装  请到 Silabs 官方网站: http://www.silabs.com/products/mcu/Pages/SoftwareDownloads.aspx?cm_sp=<WebParts>-_-<MCUSupport>-_-<SWDownloads>下载安装。1、在Silicon IDE中集成Keil软件(点击查看)2、如下图所示,点击
发表于 2020-06-30
<font color='red'>C8051F</font>仿真调试快速入门(Silicon IDE)
C8051F仿真调试快速入门(Keil)
注:下载程序必须先安装Keil软件,以及对应的Silicon IDE驱动软件·Keil的安装  请到 Keil 官方网站: https://www.keil.com/c51/demo/eval/c51.htm下载安装。·Keil μVision Driver 的安装  请到 Silabs 官方网站: http://www.silabs.com/products/mcu/Pages/KeilDriver.aspx下载安装。1、安装好Keil μVision Driver驱动并且设置好下载程序前的相关配置(点击查看)2、如下图所示,点击菜单栏中的"Debug -> Start/Stop Debug
发表于 2020-06-30
<font color='red'>C8051F</font>仿真调试快速入门(Keil)
C8051F单片机基本硬件线路设计
其实C8051F可以不需要晶振跟复位电路,但是为了最小系统能够稳定运行,所以最好增加外部电路。● C8051F复位电路设计   C8051F单片机内置上电复位,所以,C8051F单片机可以不设外部上电复位电路,依然可以正常复位,稳定工作。 若是系统需要设置按键复位电路,那么注意,C8051F单片机是低电平复位,如下图所示● C8051F震荡电路设计C8051F单片机内置RC振荡电路。在出厂设置中,并未对时钟源进行设置,用户可通过编程的方式设置内部时钟电路或是外部时钟电路,内部时钟源的最高频率为12M高速RC振荡器。通过程序对寄存器的设置,可以设置MCU的内部RC振荡频率。例如:4M、8M等。不过,内置RC振荡,在一致性
发表于 2020-06-30
<font color='red'>C8051F</font>单片机基本硬件线路设计
C8051F IO输出之LED显示程序
系统功能使用C8051F单片机控制8位LED,演示C8051F单片机之“点灯术”。硬件设计关于C8051F的I/O结构及相关介绍详见Datasheet(点击查看),这里仅对作部分简单介绍,下面是AVR的I/O引脚配置表:虽然C8051F的I/O口单独输出“1”时,可输出较大电流足已点亮一盏灯,但C8051F总的I/O输出毕竟是有限的,所以,有经验的点灯者考虑到除了点灯外可能还有其它费劲的活儿要干,会将C8051F的I/O口设计为输出“0”时点灯,输出“1”时熄灯。这种接法亦叫“灌电流接法”。8位LED灯控制电路原理图软件设计下面部分从TXT拷出,拷到网页,代码部分缺省了很多空格,比较凌乱,请谅解!//目标系统: 基于C8051F
发表于 2020-06-30
<font color='red'>C8051F</font> IO输出之LED显示程序
使用74LS164将C8051F的串口输出扩为并口输出
系统功能使用74LS164将AVR的串口输出扩为并口输出。硬件设计串行输出扩展为并行输出芯片74LS164控制电路原理图软件设计下面部分从TXT拷出,拷到网页,代码部分缺省了很多空格,比较凌乱,请谅解!//目标系统: 基于C8051F单片机//应用软件: Silicon IDE / Keil/*01010101010101010101010101010101010101010101010101010101010101010101----------------------------------------------------------------------实验内容:使用P2口的LED指示灯查看MCU自己从模拟串口发送
发表于 2020-06-30
使用74LS164将<font color='red'>C8051F</font>的串口输出扩为并口输出
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved