51单片机I2C标准函数程序

合集下载

实验八 51系列单片机IIC

实验八 51系列单片机IIC
8.3 I2C总线器件的寻址方式
I2C总线上的所有器件连接在一个公共的总线上,因此,主器件在进行数据传输前选择需要通信的从器件,即进行总线寻址。 I2C总线上所有外围器件都需要有惟一的地址,由器件地址和引脚地址两部分组成,共7位。器件地址是I2C器件固有的地址编码,器件出厂时就已经给定,不可更改。引脚地址是由I2C总线外围器件的地址引脚(A2,A1,A0)决定,根据其在电路中接电源正极、接地或悬空的不同,形成不同的地址代码。引脚地址数也决定了同一种器件可接入总线的最大数目。 地址位与一个方向位共同构成I2C总线器件寻址字节。寻址字节的格式如表所示。方向位(R/)规定了总线上的主器件与外围器件(从器件)的数据传输送方向。当方向位R/=1,表示主器件读取从器件中的数据;R/=0,表示主器件向从器件发送数据。
从地址中读取一个字节的数据
INT8U read_random(INT8U RomAddress) { INT8U Read_data; I_Start(); I_Write8Bit(WriteDeviceAddress); I_TestAck(); I_Write8Bit(RomAddress); I_TestAck(); I_Start(); I_Write8Bit(ReadDeviceAddress); I_TestAck(); Read_data=I_Read8Bit(); I_NoAck(); I_Stop(); return (Read_data); }
8.4.1 串行EEPROM存储器简介
串行EEPROM存储器是一种采用串行总线的存储器,这类存储器具有体积小、功耗低、允许工作电压范围宽等特点。目前,单片机系统中使用较多的EEPROM芯片是24系列串行EEPROM。其具有型号多、容量大、支持I2C总线协议、占用单片机I/O端口少,芯片扩展方便、读写简单等优点。 目前,Atmel、MicroChip、National等公司均提供各种型号的I2C总线接口的串行EEPROM存储器。下面以Atmel公司的产品为例进行介绍。 AT24C01/02/04/08系列是Atmel公司典型的I2C串行总线的EEPROM。这里以AT24C08为例介绍。AT24C08具有1024×8位的存储容量,工作于从器件模式,可重复擦写100万次,数据可以掉电保存100年。8引脚DIP封装的AT24C08的封装结构,如图所示。

51单片机模拟IIC工作时序,以EEPROM器件进行掉电保护数据

51单片机模拟IIC工作时序,以EEPROM器件进行掉电保护数据

51单片机软件模拟I2C时序,进行掉电保护数据在数码管上按顺序显示数据0—f(十六进制)模拟断电-切断单片机电源复位后接着断电前数据显示#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit sda=P2^0;sbit scl=P2^1;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39 ,0x5e,0x79,0x71} ;uchar num,sec,panju;//由定时器进行计数,计时,以数组的形式显示于数码管每隔1S读一次AT24C16中的数据//-------------------------------定时器0进行精确的计时,由AT24C16进行掉电保护----------------------------------//void delay(){;;}void init_timer0()//定时器初始化{TMOD=0X01;//工作方式1,GATE=0,C/~T=0,M0=0,M1=1;TH0=15536/256;//求模TL0=15536%256;//求余装入初值EA=1;ET0=1;//中断允许寄存器TR0=1;//TCON寄存器}//------------------------------------------------------------------------------------------------------------//void init_AT()//EEPROM器件初始化释放总线{scl=0;delay();//微秒延时sda=1;delay();scl=1;delay();}//----------------------------------------------------------------------------------------------------------//void start() //起始信号{scl=0;delay();sda=1;delay();scl=1;delay();sda=0;delay();sda=1;//释放数据总线//--------------------------------------------------------------------------------------------------------//void write_byte(uchar date)//字节写{uchar s,temp;//局部变量temp=date;//由高位一位一位的写入for(s=0;s<8;s++){temp=temp<<1;//左移溢出到PSW寄存器CY位scl=0;//允许sda进行的变化delay();sda=CY;//进行一位一位的送入数据总线delay();scl=1;//符合读走数据总线上数据的要求delay();//稳定一段时间}scl=0;//允许sda变化,以便于接受应答信号delay();sda=1;//释放数据总线,准备接收应答信号delay();}//--------------------------------------------------------------------------------------------------------//void response()//应答,可以看书page181,由接收设备发出的第九位数据,要经由sda传输给发送设备{uchar t;//局部变量scl=1;delay();while((sda==1)&&(t<250)){t++;//等待应答有一定的时间限制,sda被拉低表示有应答,由硬件控制}scl=0;delay();}//------------------------------------------------------------------------------------------------------//void stop()//停止信号,scl=1,sda形成一个正跳变{scl=0;//允许sda变化delay();sda=0;//准备形成正跳变delay();scl=1;//信号有效前提1delay();sda=1;//形成正跳变delay();//信号有效前提1}//-----------------------------------------------------------------------------------------------------//void delay1(uint z)//毫秒级延时{for(x=z;x>0;x--)for(y=10;y>0;y--);}//---------------------------------------------------------------------------------------------------------------//uchar read_byte()//带有返回值,将所读到的数据作为返回值{uchar i,d;//局部变量d=0x00;//清空存储变量的空间for(i=0;i<8;i++){scl=0;//允许变化,即允许传送数据,sda是serial dual date busdelay();scl=1;//允许读走数据delay();d=(d<<1)|sda;//将sda上数据放入存储变量d,也是8位ucharscl=0;delay();}return d;}//----------------------------------------------------------------------------------------------------------//void write_add(uchar address,uchar date) //任意位置,写任意内容{start();//起始信号write_byte(0xa0);//写入EEPROM器件地址,写入分为数据,地址数据,地址又分为器件地址和内部存储地址,例如某班级某学生座位response();//等待应答write_byte(address);//内部存储地址实际参数addressresponse();write_byte(date);//写入真正意义上的数据,由引入的实际参数dateresponse();//等待应答stop();//停止读取数据信号delay1(1);}//-------------------------------------------------------------------------------------------------------//uchar read_add(uchar address){uchar shu;start();write_byte(0xa0);//申明所读器件地址response();write_byte(address);//申明该器件中所要求读数据的位置response();start();write_byte(0xa1);response();shu=read_byte();//进行读数据操作后,非应答,budaixingcan,而是将返回值直接赋予变量stop();}//------------------------------------------------------------------------------------------------------------// void main(){P0=0X00;init_AT();sec=read_add(0X03);//将芯片中数据读出;作为基数init_timer0();//定时器初始化设置if(sec==16)sec=0;while(1){P0=table[sec];if(panju==1){panju=0;write_add(0x03,sec);}}}//---------------------------------------------------------------------------------------------------------// void timer0_break() interrupt 1{TH0=15536/256;//求模TL0=15536%256;//求余装入初值num++;if(num==20){num=0;sec++;panju=1;if(sec==16) sec=0;}}。

C51单片机模拟I2C总线驱动程序设计

C51单片机模拟I2C总线驱动程序设计

_nop_(); } SCL = 0; _nop_(); _nop_(); return(retc); } /************************************ I2C_Ackn ******************************** 函数名:void I2C_Ackn(bit a) 入口:0 或 1 出口: 功能描述:主控制器进行应答信号(可以是应答或非应答信号) 说明:作为接收方的时候,必须根据当前自己的状态向发送器反馈应答信号 调用函数: 全局变量: *******************************************************************************
//位
retc = 0; SDA = 1; //置数据总线为输入方式,作为接收方要释放 SDA. for(BitCnt=0;BitCnt<8;BitCnt++) { _nop_(); SCL = 0; //置时钟线为低准备接收数据位 SomeNOP(); //时钟低电平周期大于 4.7us SCL = 1; //置时钟线为高使数据有效 _nop_(); _nop_(); retc = retc<<1; if(SDA==1) { retc = retc + 1; //读数据位,接收的数据放入 retc 中 } _nop_();
//发送器件子地址
//发送数据
//结束总线
/********************************** I2C_IRcvB ********************************* 函数名:bit I2C_IRcvB(uchar sla, uchar suba, uchar *c) 入口:从器件地址 sla, 子地址 suba, 收到的数据在 c 出口:1(操作成功),0(操作有误) 功能描述:从启动总线到发送地址、读数据,结束总线的全过程。

51单片机I2C总线驱动程序

51单片机I2C总线驱动程序

51单片机I2C总线驱动程序SI2I2C 总线是PHLIPS 公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。

I2C 总线只有两根双向信号线。

一根是数据线SDA,另一根是时钟线SCL。

一.I2C 系统结构每个接到I2C 总线上的器件都有唯一的地址。

主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。

由总线上接收数据的器件则为接收器。

二.数据位的有效性规定I2C 总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

三.字节传送与应答每一个字节必须保证是8 位长度。

数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9 位)。

四.驱动程序#define uchar unsigned char#define uint unsigned int#define somenop() _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_()sbit SCL=P2;sb it SDA=P2;123451.起始信号和终止信号SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态void I2C_Start() //起始{SCL=1;somenop();SDA=1;somenop(); SDA=0;somenop();SCL=0;somenop();}void I2C_Stop() //终止{ SDA=0;somenop();SCL=1;somenop();SDA=1;somenop();}12345678910111213141。

MPU6050使用I2C协议读出X轴原始数据的51单片机程序

MPU6050使用I2C协议读出X轴原始数据的51单片机程序

MPU6050使用I2C协议读出X轴原始数据的51单片机程序主:STC89C54下面代码#include <reg51.h>#define uchar unsigned char//#define addr_x 0xae // 写//#define addr_d 0xaf // 读sbit sda = P2^1; //数据管脚sbit scl = P2^0; //时钟管脚bit ack;//****************************************// 定义MPU6050内部地址//****************************************#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)#define ACCEL_XOUT_H 0x3B#define ACCEL_XOUT_L 0x3C#define ACCEL_YOUT_H 0x3D#define ACCEL_YOUT_L 0x3E#define ACCEL_ZOUT_H 0x3F#define ACCEL_ZOUT_L 0x40#define TEMP_OUT_H 0x41#define TEMP_OUT_L 0x42#define GYRO_XOUT_H 0x43#define GYRO_XOUT_L 0x44#define GYRO_YOUT_H 0x45#define GYRO_YOUT_L 0x46#define GYRO_ZOUT_H 0x47#define GYRO_ZOUT_L 0x48#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取void DelayUs2x(unsigned char t) //延时1{while(--t);}void DelayMs(unsigned char t) //延时2{while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}void delay() //延时大于4μs//*******************I2C操作协议******************************void i2_qs() //起始信号{sda = 1; //拉高数据scl = 1; //拉高时钟delay(); //延时大于 4μssda = 0; //拉低数据产生起始信号(下降沿)delay(); //延时大于 4μsscl = 0; //拉低时钟delay(); //延时大于 4μs}void i2_tz() //停止信号{sda = 0; //拉低数据scl = 1; //拉高时钟delay(); //延时大于 4μssda = 1; //拉高时钟产生结束信号(上升沿)delay(); //延时大于 4μs}void i2_ack(bit _ack) //入口产生 0 ack 1 nak{sda = _ack; //ack或者nakscl = 1; //拉高时钟delay(); //延时大于 4μsscl = 0; //拉低时钟delay(); //延时大于 4μsvoid i2_fs(uchar Data) //发送8位数据{uchar i;for(i=0;i<8;i++) //8位计数{Data <<= 1; //把最高位移送到进制标志位中(CY)sda = CY; //把进制位中的数据赋值给数据线scl = 1; //拉高时钟delay(); //延时大于 4μsscl = 0; //拉低时钟//这里}//下面代码是接收ACK的代码delay();//延时大于 4μssda = 1; //拉高数据准备接收ACKscl = 1; //拉高时钟产生稳定的有效的数据(相对的)if(sda==1) //确认接收的是ACK还是NAKack = 0;//ackelseack = 1;//nakscl = 0; //拉低时钟delay(); //延时大于 4us}uchar i2_js() //接收8位数据{uchar i,Data = 0;sda = 1; //使能内部上拉,准备读取数据for(i=0;i<8;i++) //8位计数器{Data <<= 1; //移出数据的最高位scl = 1; //拉高时钟delay(); //延时大于 4usData |= sda;//接收数据scl = 0; //拉低时钟delay(); //延时大于 4us}return Data;}void i2_sj_x(uchar addr,uchar Data) //往设备内写入数据(参数1、寄存器地址 2、写入的数据){i2_qs(); //起始信号i2_fs(SlaveAddress); //设备地址+写信号i2_fs(addr); //寄存器内部地址i2_fs(Data); //写入设备的数据i2_tz(); //停止信号}uchar i2_sj_d(uchar addr) //读取数据(参数寄存器地址){uchar Data;i2_qs(); //起始信号i2_fs(SlaveAddress); //设备地址+写信号i2_fs(addr); //寄存器内部地址i2_qs(); //起始信号i2_fs(SlaveAddress+1); //设备地址+读信号Data = i2_js(); //读取数据i2_ack(0); //ACK应答i2_tz(); //停止信号return Data; //返回读取的数据}//*******************I2C操作协议******************************void mup6050(){i2_sj_x(PWR_MGMT_1, 0x00);i2_sj_x(SMPLRT_DIV, 0x07);i2_sj_x(CONFIG, 0x06);i2_sj_x(GYRO_CONFIG, 0x18);i2_sj_x(ACCEL_CONFIG, 0x01);/*Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态Single_WriteI2C(SMPLRT_DIV, 0x07); //陀螺仪采集频率Single_WriteI2C(CONFIG, 0x06);//低通滤波频率Single_WriteI2C(GYRO_CONFIG, 0x18);//陀螺仪自检及测量范围Single_WriteI2C(ACCEL_CONFIG, 0x01);//加速计自检、测量范围及高通滤波频率*/}/**************************************串口**********************************/void CSH (void) //初始化串口SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装TH1 = 0xFD; // TH1: 重装值9600 波特率晶振11.0592MHzTR1 = 1; // TR1: timer 1 打开EA = 1; //打开总中断//ES = 1; //打开串口中断}void SendByte(unsigned char dat) //发送一个字符{SBUF = dat; //SBUF 串行数据缓冲器while(!TI); //TI发送中断标志位 (当数据发送完毕后由硬件置 1 否则等待硬件置 1)TI = 0;}/************************************************************** **********************/void main(void){uchar dat1,dat2,i;mup6050();CSH();/*i2_sj_x(3,0x0f); //数据写入24c02DelayMs(50);dat = i2_sj_d(3); //从24c02中读取数据//P1 = dat; //使用8个LED显示读出的数据while(1){dat1 = i2_sj_d(GYRO_XOUT_H);dat2 = i2_sj_d(GYRO_XOUT_H+1);P1 = dat1;for(i=0;i<100;i++)DelayMs(10);P1 = dat2;for(i=0;i<100;i++)DelayMs(10);SendByte(dat1);SendByte(dat2);}}。

I2C程序和流程图

I2C程序和流程图

程序和流程图:IIC.hvoid Init_IIC(void);void EEPROM_ByteWrite(unsigned char nAddr,unsigned char nVal); unsigned char EEPROM_RandomRead(unsigned char nAddr); unsigned char EEPROM_CurrentAddressRead(void);void EEPROM_AckPolling(void);void Init_CLK(void);void Init_IIC_Port(void);Main.C/*******************************************IIC for AT24c16 OR AT24CXXX 系列只要控制好IICRM IICSTP IICSTT 其硬件会自动完成SCL SDA的一系列时序只要注意各个发送与接收的控制标志位.******************************************/#include <MSP430x16x.h>#include "IIC.h"volatile unsigned char Data[6];void main(void){//volatile unsigned char Data[6];//停止看门狗WDTCTL = WDTPW+WDTHOLD;//初始化端口Init_IIC_Port();//初始化时钟Init_CLK();//I2C初始化Init_IIC(); //置传输方式及控制方式//打开中断_EINT();//写入数据EEPROM_ByteWrite(0x0000,0x12);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0001,0x34);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0002,0x56);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0003,0x78);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0004,0x9A);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0005,0xBC);//等待写操作完成EEPROM_AckPolling();//读出数据,随机读Data[0] = EEPROM_RandomRead(0x0000); //地址自动加1 //读出数据,当前地址读Data[1] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[2] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[3] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[4] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[5] = EEPROM_CurrentAddressRead();}IIC.C#include <MSP430x16x.h>#include "IIC.h"#define SLAVEADDR 0x50;int tx_count;int rx_count;unsigned char I2CBuffer[3];void Init_IIC(void){//将P3.1和P3.3设置为I2C管脚P3SEL = 0x0A;//设置P3.1和P3.3管脚的方向P3DIR &= ~0x0A;//选择为I2C模式U0CTL |= I2C + SYNC;//禁止I2C模块U0CTL &= ~I2CEN;//设置I2C为7位地址模式,不使用DMA,//字节模式,时钟源为SMCLK,//设置成传输模式I2CTCTL = I2CTRX + I2CSSEL_2;//定义从器件地址I2CSA = SLAVEADDR;//设置本身的地址I2COA = 0x01A5;//I2C时钟为SMCLK / 160I2CPSC = 159;//SCL 高电平为:5 *I2C 时钟I2CSCLH = 0x03;//SCL 低电平为:5 *I2C 时钟I2CSCLL = 0x03;//I2C 模块有效U0CTL |= I2CEN;tx_count = 0;rx_count = 0;}void I2CWriteInit(void) //对于AT24CXXX的写操作是置成主模式并置位中断使能. {//主(Master)模式U0CTL |= MST;//传输模式,R/W 为:0I2CTCTL |= I2CTRX;//清除中断标志I2CIFG &= ~TXRDYIFG;//发送中断使能I2CIE = TXRDYIE;}void I2CReadInit(void){//接收模式,R/W 为:1I2CTCTL &= ~I2CTRX;//接收中断使能I2CIE = RXRDYIE;}void EEPROM_ByteWrite(unsigned char nAddr, unsigned char nVal){//等待I2C模块完成所有操作 //在选定的地址写入数据.while (I2CDCTL&I2CBUSY) ;//设置地址数据I2CBuffer[1] = nAddr;//设置数据I2CBuffer[0] = nVal;//设置缓冲区指针tx_count = 1;//写数据初始化I2CWriteInit(); //设置为主模式//发送数据的长度//1个控制字节,2个数据字节I2CNDAT = 2;//开始和停止条件产生//开始I2C通信I2CTCTL |= I2CSTT+I2CSTP;return;}unsigned char EEPROM_CurrentAddressRead(void){//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);//读操作的初始化I2CReadInit();//主(Master)模式U0CTL |= MST;//接收1个字节的数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//开始接收,产生重新起始和停止条件I2CTCTL |= I2CSTT + I2CSTP;//等待传输完成while ((~I2CIFG)&ARDYIFG) ;//返回数据return I2CBuffer[0];}unsigned char EEPROM_RandomRead(unsigned char nAddr) {//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);//设置地址I2CBuffer[0] = nAddr;//设置缓冲区指针tx_count = 0;//写操作初始化I2CWriteInit();//传输数据长度//1个控制字节和一个地址数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//起始条件产生I2CTCTL |= I2CSTT;//等待传输完成while ((~I2CIFG)&ARDYIFG);//读操作初始化I2CReadInit();//接收一个字节的数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//开始接收,产生重新起始和停止条件 I2CTCTL |= I2CSTT + I2CSTP;//等待传输完成while ((~I2CIFG)&ARDYIFG);//返回数据return I2CBuffer[0];}void EEPROM_AckPolling(void){unsigned int count;//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);count=0;//清除I2CEN位U0CTL &= ~I2CEN;I2CTCTL |= I2CRM;//使能I2C模块U0CTL |= I2CEN;//设置NACKIFG标志I2CIFG = NACKIFG;while (NACKIFG & I2CIFG){//清除中断标志I2CIFG=0x00;//主(Master)模式U0CTL |= MST;//设置传输模式I2CTCTL |= I2CTRX;//产生起始条件I2CTCTL |= I2CSTT;//等待I2CSTT被清除while (I2CTCTL & I2CSTT) ; //产生停止条件I2CTCTL |= I2CSTP;//等待停止条件复位while (I2CDCTL & I2CBUSY) ; count = count + 1;}//清除I2CEN位U0CTL &= ~I2CEN;I2CTCTL &= ~I2CRM;//使能I2CU0CTL |= I2CEN;return;}#if __VER__ < 200interrupt [USART0TX_VECTOR] void ISR_I2C(void)#else#pragma vector=USART0TX_VECTOR__interrupt void ISR_I2C(void)#endif //上面的程序其实只要编写 ://#pragma vector=USART0TX_VECTOR __interrupt void ISR_I2C(void)就行. {switch (I2CIV){case I2CIV_AL:{//仲裁中断break;}case I2CIV_NACK:{//NACK中断break;}case I2CIV_OA:{//自己地址中断break;}case I2CIV_ARDY:{//访问准备好中断break;}case I2CIV_RXRDY:{//接收准备好中断I2CBuffer[0]=I2CDRB;break;}case I2CIV_TXRDY:{//发送准备好中断I2CDRB = I2CBuffer[tx_count];tx_count = tx_count - 1;if (tx_count < 0){//禁止发送中断I2CIE &= ~TXRDYIE;}break;}case I2CIV_GC:{//一般调用中断break;}case I2CIV_STT:{//起始条件中断break;}}}void Init_IIC_Port(void){//初始化端口寄存器与IIC口无关的PX口关闭以便于对编写系统板的综合程序. //P1DIR = 0xFF;//P2DIR = 0xFF;P3DIR = 0xF5;//P4DIR = 0xFF;P5DIR = 0x7F;//P6DIR = 0xFF;//P4OUT = 0X11;//P5OUT &= 0XF0;P3SEL|=BIT1+BIT3; //在这里如果设置成}void Init_CLK(void){unsigned int i;//将寄存器的内容清零//XT2震荡器开启//LFTX1工作在低频模式//ACLK的分频因子为1BCSCTL1 = 0X00;do{// 清除OSCFault标志IFG1 &= ~OFIFG;for (i = 0x20; i > 0; i--);}while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1//open XT2, LFTX2 选择低频率BCSCTL1 &= ~(XT2OFF + XTS); //BCSCTL1=0X00 功能一样//DCO Rsel=7(Freq=3200k/25摄氏度)BCSCTL1 |= RSEL0 + RSEL1 + RSEL2;BCSCTL1 |= 0x07;//MCLK的时钟源为TX2CLK,分频因子为1BCSCTL2 += SELM1;//SMCLK的时钟源为TX2CLK,分频因子为1BCSCTL2 += SELS;}//对于系统时钟的选择关系到整个程序运行稳定性./*************************************************************文件名:msp430f169i2c.c*整体描述:MSP430F169单片机硬件IIC软件,字节方式,主方式* IIC接口:P3.3=SCL,P3.1=SDA;(开漏输出)* 相应寄存器:地址寄存器I2COA 用于存放自身从地址(从方式时才有用)* 地址寄存器I2CSA 用于存放外围的从机地址(主方式时才有用)* 控制寄存器U0CTL 硬件I2C的设置、使能、模式等。

I2C 原代码

I2C 原代码
SlaveAddr:从机地址(高7位是从机地址,最低位是读写标志)
SubAddr: 从机的子地址
size: 数据大小(以字节计)
*dat: 要发送的数据
返回:
0:发送成功
1:在发送过程中出现异常
******************************************************************************/
SubAddr:从机的子地址
size:数据大小(以字节计)
*dat:保存接收到的数据
返回:
0:接收成功
1:在接收过程中出现异常
******************************************************************************/
bit I2C_sendbtyes(unsigned char SlaveAddr,unsigned char SubAddr,unsigned char size,unsigned char *dat)
{
SlaveAddr &= 0xFE; //确保从机地址最低位是0
I2C_Write(SubAddr); //发送子地址
if ( I2C_GetAck() ){I2C_Stop(); return 1; }
L = 1; I2C_Delay();
I2C_SDA = 1; I2C_Delay();
}
/******************************************************************************
函数:I2C_Start()

I2C总线及单片机模拟I2C总线通信程序编写

I2C总线及单片机模拟I2C总线通信程序编写

I2C总线及单片机模拟I2C总线通信程序编写1、I2C总线I2C总线是Inter-IntegratedCircuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。

I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。

所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。

2、数据有效性、起始和终止信号数据位的有效性:I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

起始信号:SCL线为高电平期间,SDA线由高电平向低电平的变化;终止信号:SCL线为高电平期间,SDA线由低电平向高电平的变化。

起始信号和终止信号都由主机发出。

3、数据传送格式1)字节传送与应答每一个字节必须保证是8位长度。

数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。

如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。

2)数据帧格式I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。

在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。

每次数据传送总是由主机产生的终止信号结束。

若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。

在总线的一次数据传送过程中,可以有以下几种组合方式:a、主机向从机发送数据,数据传送方向在整个传送过程中不变:注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

51单片机I2C标准函数程序
#include<REG52.h>
#include<intrins.h>
#include<stdio.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit SDA=P1^1;
sbit SCL=P1^0;
//===================================================== =========================
void Start()//开始信号
{
SDA=1;
SCL=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SCL=0;
}
/************************************************************ ******************/
void Stop() //停止信号
{
SDA=0;
SCL=1;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
SDA=0;
SCL=0;
}
/************************************************************ ******************/
void Ack()//应答信号
{
SDA=0;
SCL=1;
_nop_();
_nop_();
SCL=0;
SDA=1;
}
/************************************************************ ******************/
void NoAck() //非应答信号
{
SDA=1;
SCL=1;
_nop_();
_nop_();
SCL=0;
SDA=0;
}
/************************************************************ ******************/
bit TestACk()//检查应答信号
{
bit Cack=0;
SDA=1;
SCL=1;
Cack=SDA;
SCL=0;
return(Cack);
}
/************************************************************ ******************/
void WriteByte(uchar input)//向I2C从设备中写入1字节
{
uchar i;
for(i=8;i!=0;i--)
{
SDA=(bit)(inupt&0x80);
SCL=1;
_nop_();
_nop_();
input=input<<1;
}
}
/************************************************************ ******************/
/*向有内部地址的器件写入多字节,ads为器件地址,sads为器件内部地址,指针wp指向要
发送的字节,no为字节数。

发送成功返回1,失败返回0。

*/
bit Write_nB_sads(uchar ads,uchar sads,uchar *wp,uchar no)
{
uchar i;
BEGIN:
Start(); //启动总线
WriteByte(ads); //发送器件地址
if(TestAck()) goto BEGIN;
WriteByte(sads); //发送器件分地址
if(TestAck()) goto BEGIN;
for(i=0;i<no;i++)
{
WriteByte(*wp); //发送数据
if(TestAck()) goto BEGIN;
wp++;
}
Stop(); //释放总线
return(1);
}
/************************************************************ ******************/
uchar ReadByte()//从I2C从设备中读出1字节
{
uchar i;rbyte=0;
SDA=1;
for(i=8;i!=0;i--)
{
rbyte=rbyte<<1;
rbyte=rbyte|((uchar)(SDA));
SCL=0;
}
return(rbyte);
}
/************************************************************ ******************/
/*向有内部地址的器件写入多字节,ads为器件地址,sads为器件内部地址,读出的数据存在
指针rp指向的内存空间,no为字节数。

读出成功返回1,失败返回0。

*/
bit Read_nB_sads(uchar ads,uchar sads,uchar *rp,uchar no)
{
uchar i;
BEGIN:
Start(); //启动总线
WriteByte(ads); //发送器件地址
if(TestAck()) goto BEGIN;
WriteByte(sads); //发送器件分地址
if(TestAck()) goto BEGIN;
Start(); //启动
WriteByte(ads+1);
if(TestAck()) goto BEGIN;
for(i=0;i<no;i++)
{
*rp=ReadByte(); //发送应答位
Ack();
rp++;
}
*rp=ReadByte();
NoAck(); //发送非应答位
Stop(); //释放总线
return(1); }
void main() {
}。

相关文档
最新文档