i2c简易时序图

合集下载

I2C存储器读写(计数器,并能断电存储)

I2C存储器读写(计数器,并能断电存储)

任务二:I2C存储器读写(计数器,并能断电存储)之阿布丰王创作实验原理1)I2C总线概述I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线判决和高低速器件同步功能的高性能串行总线.2)I2C信号线I2C总线只有两根双向信号线.一根是数据线SDA,另一根是时钟线SCL.I2C总线通过上拉电阻接正电源.当总线空闲时,两根线均为高电平.连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系.图 1 I2C总线框图3)I2C总线的数据传送a)数据位的有效性规定I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必需坚持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变动.图 2 SDA与SCL的工作时序图b) 起始和终止信号SCL线为高电平期间,SDA线由高电平向低电平的变动暗示起始信号SCL线为高电平期间,SDA线由低电平向高电平的变动暗示终止信号.起始和终止信号都是由主机发出的,在起始信号发生后,总线就处于被占用的状态;在终止信号发生后,总线就处于空闲状态.c) I2C总线的数据传送速率I2C总线的通信速率受主机控制,能快能慢,最高速率限制为100Kb/sd) I2C总线的数据传送格式主机向从机发送数据从机向主机发送数据图 3 I2C总线的数据传送格式S:起始位 SA: 从机地址,7位W/:写标识表记标帜位,1位 R:读标识表记标帜位,1位A:应答位,1位 A/:非应答位,1位D:数据,8位 P:停止位阴影:主机发生的信号无阴影:从机发生的信号4)总线的寻址I2C总线协议有明确的规定:采纳7位的寻址字节(寻址字节是起始信号后的第一个字节).寻址字节的位界说D7~D1位组成从机的地址.D0位是数据传送方向位,为“0”时暗示主机向从机写数据,为“1”时暗示主机由从机读数据.主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比力,如果相同,则认为自己正被主机寻址,根据R/位将自己确定为发送器或接收器.从机的地址由固定部份和可编程部份组成.在一个系统中可能希望接入多个相同的从机,从机地址中可编程部份决定了可接入总线该类器件的最年夜数目.如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中.任务三:要求:设计一个简单系统,每10S进行温度收集(结合电路与法式,分析指标),在液晶屏上显示以后温度和前一状态的温度,并将结果存入存储器,具备可将温度的存储结果与PC机通讯和数据发送功能,可以使用键盘设定温度高低限制值,到达限制值时报警.一、实验设计思路二、实验内容1、蜂鸣器工作原理蜂鸣器发声原理是电流通过电磁线圈,使电磁线圈发生磁场来驱动振动膜发声的,因此需要一定的电流才华驱动它,单片机IO引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放年夜的电路.原理图见图:如图所示,蜂鸣器的负极经电阻R3接地,蜂鸣器的正极接到三极管的集电极C,三极管的基级B经过限流电阻R2后由单片机的P1.3引脚控制,当P1.3输出高电平时,三极管Q1截止,没有电流流过线圈,蜂鸣器不发声;当P1.3输出低电平时,三极管导通,这样蜂鸣器的电流形成回路,发作声音.因此,我们可以通过法式控制P1.3脚的电平来使蜂鸣器发作声音和关闭.法式中改变单片机P1.3引脚输出波形的频率,就可以调整控制蜂鸣器音调,发生各种分歧音色、音调的声音.另外,改变P1.3输出电平的高低电平占空比,则可以控制蜂鸣器的声音年夜小.2、SP2键盘控制数据格式数据发送时序一个键盘发送值的例子:通码和断码是以什么样的序列发送到你的计算机从而使得字符G 呈现在你的字处置软件里的呢?因为这是一个年夜写字母,需要发生这样的事件次第:按下Shift 键-按下G键-释放G 键-释放Shift 键.与这些时间相关的扫描码如下:Shift 键的通码12h,G 键的通码34h ,G 键的断码F0h 34h ,Shift 键的断码F0h 12h .因此发送到你的计算机的数据应该是:12h 34h F0h 34h F0h 12h3、DS18B20温度传感器DS18B20工作原理及应用:DS18B20的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强.其一个工作周期可分为两个部份,即温度检测和数据处置.在讲解其工作流程之前我们有需要了解18B20的内部存储器资源.18B20共有三种形态的存储器资源,它们分别是:ROM 只读存储器,用于寄存DS18B20ID编码,其前8位是单线系列编码(DS18B20的编码是19H),后面48位是芯片唯一的序列号,最后8位是以上56的位的CRC码(冗余校验).数据在生产时设置不由用户更改.DS18B20共64位ROM.RAM 数据暂存器,用于内部计算和数据存取,数据在失落电后丧失,DS18B20共9个字节RAM,每个字节为8位.第1、2个字节是温度转换后的数据值信息,第3、4个字节是用户EEPROM(经常使用于温度报警值贮存)的镜像.在上电复位时其值将被刷新.第5个字节则是用户第3个EEPROM的镜像.第6、7、8个字节为计数寄存器,是为了让用户获得更高的温度分辨率而设计的,同样也是内部温度转换、计算的暂存单位.第9个字节为前8个字节的CRC 码.EEPROM 非易失性记忆体,用于寄存长期需要保管的数据,上下限温度报警值和校验数据,DS18B20共3位EEPROM,并在RAM都存在镜像,以方便用户把持.4、LCD1602液晶显示读写把持时序如图所示图三:读把持时序图四:写把持时序附录一:(任务二法式)#include <p18f452.h>#include <i2c.h>#define uint unsigned int#define uchar unsigned char#define e PORTBbits.RB3//液晶屏e端接RB3#define rw PORTBbits.RB4//液晶屏rw端接RB4#define rs PORTBbits.RB5//液晶屏rs端接RB5void disp(uchar num1,uchar num2,uchar num3);void delay(uint z);void disp_init(void); //液晶屏初始化void write_com(uchar com);//对液晶屏写指令void write_data(uchar dat);//写数据void main(void){unsigned int lednum=0,x,tt=0; //lednum 显示的数据,x 24c02读到的数据,tt时间累加unsigned int a1=0,a2=0,a3=0; //显示位数个十百 disp_init();//1602的初始化OpenI2C(MASTER, SLEW_ON);//I2C 的初始化SSPADD = 9; //频率为400KHZT0CONbits.TMR0ON=0;//关闭TIMER0 T0CONbits.T08BIT=0;//配置为16位计数模式T0CONbits.T0CS=0;//选择内部时钟源即按时模式TMR0H=(65536-10000)/256;//按时5us TMR0L=(65536-10000)%256;INTCONbits.TMR0IF=0;//清TIMER0溢出中断标识表记标帜位T0CONbits.TMR0ON=1;//使能TIMER0 while(1){x = EERandomRead(0xA0,0x03);//读数据,0XA0为器件地址 0X03为存储地址 if(INTCONbits.TMR0IF==1)//TIMER0溢出中断标识表记标帜位为1 {INTCONbits.TMR0IF=0;//清TIMER0溢出中断标识表记标帜位TMR0H=(65536-10000)/256;//5us*10000=50msTMR0L=(65536-10000)%256;tt++;if(tt==20)//1s{tt=0;x++;if(x==256){x=0;}EEByteWrite(0xA0, 0x03,x); //写数据EEAckPolling(0xA0);//应答}}lednum = EERandomRead(0xA0,0x03);//防止断电遗失a1=lednum/100;//百位上的数字a2=lednum%100/10;//十位上的数字a3=lednum%10;//个位上的数字disp(a1,a2,a3);//显示}}void write_com(uchar com)//LED1602控制字输入{TRISB=0b000000000;//TRISB=0b00010000;TRISD=0;e=0;rw=0;rs=0; //写指令:RS=L,RW=L,D0~D7=指令码,E=高脉冲PORTD=com; //写指令到液晶delay(5);e=1;delay(5);e=0;}void write_data(uchar dat)//LCD1602数据输入{ TRISD=0;e=0;rw=0;rs=1;//写数据:RS=H,RW=L,D0~D7=指令码,E=高脉冲PORTD=dat;//写数据到液晶delay(5);e=1;delay(5);e=0;}void disp_init(){TRISD=0;//选择D端口为液晶屏数据的输入口write_com(0x38);//液晶开显示write_com(0x0c);//显示光标,光标闪烁write_com(0x06);//读或写一个字符后地址指针加一,光标加一write_com(0x01);//显示清屏:1、数据指针清零;2、所有显示清零write_com(0x80);//第一行首位}void disp(uchar num1,uchar num2,uchar num3){write_com(0x80+0x40);write_data(num1+0x30);//液晶第二行第一位数delay(1);write_com(0x80+0x41);write_data(num2+0x30);//液晶第二行第二位数delay(1);write_com(0x80+0x42);write_data(num3+0x30);//液晶第二行第三位数delay(1);}void delay(uint z)//z毫秒延时子法式{uint x,y;for(x=110;x>0;x--)for(y=z;y>0;y--);}附录二(任务三法式)#include <pic18.h> //调用头文件,可以去PICC18软件下去查找PIC18FXX2.H__CONFIG(1,XT) ; //晶振为外部4M__CONFIG(2,WDTDIS) ; //看门狗关闭__CONFIG(4,LVPDIS) ; //禁止低电压编程#define RSPIN RB5 //Data or Instrument Select LCD1602#define RWPIN RB4 //Write or Read#define EPIN RB3 //6800 mode Enable singleunsigned char temp1=0,temp1_1=0; //收集到的温度高8位上一次的unsigned char temp2=0,temp2_2=0; //收集到的温度低8位unsigned int a,b,c=0;#define beep RC2 //界说蜂鸣器接口/****************************************/#define sda RC4 //AT24C02#define scl RC3bit eepromdi;bit eepromdo;unsigned char addressbuf;unsigned char buf_24C02;/****************************************/bit clrbit; //USARTunsigned char recebuf;/****************************************///转换后的温度值小数点部份查表const unsigned char tablexiao[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};/***************************************************************************** ***********/#define Key_Data RB1#define Key_CLK RB0unsigned char IntNum; //中断次数计数unsigned char KeyV; //键值unsigned char Key_UP=0, Shift = 0;//Key_UP是键松开标识,Shift是Shift键按下标识unsigned char keybuf;unsigned char disbuf;//84unsigned char shu1=0,shu2=0,tem1=0,tem2=0,tem3=0; //温度上限bit bf; //标识是否有字符被收到bit disbit;//0x66为backspace键//0x5a为Enter键const unsigned char UnShifted[59][2] = {0x1C, 'a',0x32, 'b',0x21, 'c',0x23, 'd',0x24, 'e',0x2B, 'f',0x34, 'g',0x33, 'h',0x43, 'i',0x3B, 'j',0x42, 'k',0x4B, 'l',0x3A, 'm',0x31, 'n',0x44, 'o',0x4D, 'p',0x15, 'q',0x2D, 'r',0x1B, 's',0x2C, 't',0x3C, 'u',0x2A, 'v',0x1D, 'w',0x22, 'x',0x35, 'y',0x1A, 'z',0x45, '0',0x16, '1',0x1E, '2',0x26, '3',0x25, '4',0x2E, '5',0x36, '6',0x3D, '7',0x3E, '8',0x46, '9',0x0E, '`',0x4E, '-',0x55, '=',0x5D, '\\',0x29, ' ',0x54, '[',0x5B, ']',0x4C, ';',0x52, '\'',0x41, ',',0x49, '.',0x4A, '/',0x71, '.',0x70, '0',0x69, '1',0x72, '2',0x7A, '3',0x6B, '4',0x73, '5',0x74, '6',0x6C, '7',0x75, '8',0x7D, '9',};const unsigned char Shifted[59][2] = { 0x1C, 'A',0x32, 'B',0x21, 'C',0x23, 'D',0x24, 'E',0x2B, 'F',0x34, 'G',0x33, 'H',0x43, 'I',0x3B, 'J',0x42, 'K',0x4B, 'L',0x3A, 'M',0x31, 'N',0x44, 'O',0x4D, 'P',0x15, 'Q',0x2D, 'R',0x1B, 'S',0x2C, 'T',0x3C, 'U',0x2A, 'V',0x1D, 'W',0x22, 'X',0x35, 'Y',0x1A, 'Z',0x45, '0',0x16, '1',0x1E, '2',0x26, '3',0x25, '4',0x2E, '5',0x36, '6',0x3D, '7',0x3E, '8',0x46, '9',0x0E, '~',0x4E, '_',0x55, '+',0x5D, '|',0x29, ' ',0x54, '{',0x5B, '}',0x4C, ':',0x52, '"',0x41, '<',0x49, '>',0x4A, '?',0x71, '.',0x70, '0',0x69, '1',0x72, '2',0x7A, '3',0x6B, '4',0x73, '5',0x74, '6',0x6C, '7',0x75, '8',0x7D, '9',};//******************************************************************/ //6x8.h文件:/*-----------------------------------------------6 x 8 font1 pixel space at left and bottomindex = ASCII - 32-----------------------------------------------*/const unsigned char font6x8[][6] ={{ 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },// ! { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },// " { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },// # { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 },// $ { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 },// %5 { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 },// & { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 },// ' { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 },// ( { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 },// ) { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 },// * { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 },// + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 },// , { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 },// - { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },// . { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 },// / { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E },// 0 16 { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 },// 1 { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 },// 2 { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 },// 3 { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 },// 4 { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 },// 5 { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 },// 6 { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 },// 7 { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 },// 8 { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E },// 9 { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 },// : 26 { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 },// ; { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },// < { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 },// = { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 },// > { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 },// ? { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E },// @ { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C },// A33 { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 },// B { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 },// C { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C },// D { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 },// E { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 },// F { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A },// G { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F },// H { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 },// I { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 },// J { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 },// K { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 },// L { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F },// M { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F },// N { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E },// O { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 },// P { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E },// Q { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 },// R { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 },// S { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 },// T { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F },// U { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F },// V { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F },// W { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 },// X{ 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 },// Z{ 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 },// [59{ 0x00, 0x02, 0x04, 0x08, 0x10, 0x20 },// '\'{ 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 },// ]{ 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 },// ^{ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 },// _{ 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 },// '{ 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 },// a 65{ 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 },// b{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 },// c{ 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F },// d{ 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 },// e{ 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 },// f{ 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C },// g{ 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 },// h{ 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 },// i{ 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 },// j{ 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 },// k{ 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 },// l{ 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 },// m{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 },// n{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 },// o{ 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 },// p{ 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC },// q{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 },// r{ 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 },// s{ 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 },// t{ 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C },// u{ 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C },// v{ 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C },// w{ 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 },// x{ 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C },// y{ 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 },// z 90{ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 },// | 91{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }// horiz lines};/***************************************************************************** **************************/void delay(unsigned char x,unsigned char y){unsigned char z;do{z=y;do{;}while(--z);}while(--x);}//名称: 复位DS18B20函数unsigned char reset(void){unsigned char outbit;TRISA4=0;//设置RA4位输出口RA4=0; //设置RA4=0;delay(2,70); //延时503usTRISA4=1; //设置RA4为输入口,以释放总线等电阻拉高总线delay(2,8); //延时70usif(RA4==1) outbit=0; //没有接收到应答信号,继续复位else outbit=1; //接收到应答信号delay(2,60); //延时430usreturn outbit; //带参数返回,如果接收到应答,返回1,否则返回0 }//名称: 写字节函数void write_byte(unsigned char val){unsigned char i;unsigned char temp;for(i=8;i>0;i--){temp=val&0x01; //最低位移出TRISA4=0;//设置RA4位输出口RA4=0; //设置RA4=0;NOP();NOP();NOP();NOP();NOP(); //从高拉至低电平,发生写时间隙if(temp==1) TRISA4=1; //如果写1,拉高电平delay(2,7); //延时63usTRISA4=1; //设置RA4为输入口,以释放总线等电阻拉高总线NOP();NOP();val=val>>1; //右移一位}}//名称: 读字节函数unsigned char read_byte(void){unsigned char i;unsigned char value=0; //读出温度for(i=8;i>0;i--){value>>=1;TRISA4=0;//设置RA4位输出口RA4=0; //设置RA4=0;NOP();NOP();NOP();NOP();NOP();NOP(); //6usTRISA4=1; //设置RA4为输入口NOP();NOP();NOP();NOP(); //4usif(RA4==1) value|=0x80; //如果接收到数据为1,从最高位往右移delay(2,7); //63us}return(value);}//名称: 启动读温度函数void convert_T(void){if(reset()==1) //如果复位胜利{write_byte(0xcc); // 跳过多器件识别write_byte(0x44); // 启动温度转换}}//名称: 读温度函数void read_T(void){unsigned char Lsb,Msb;if(reset()==1){write_byte(0xcc); // 跳过多器件识别write_byte(0xbe); // 读暂存器Lsb=read_byte(); // 低字节Msb=read_byte(); // 高字节temp2=Lsb&0x0f; //LSB的低4位为小数部份temp1=(Lsb>>4)|(Msb<<4);//LSB的高4位和MSB拼成整数部份 }}//名称: 延时函数void delay1(unsigned int t){unsigned int i,j;for(i=0;i<t;i++){for(j=0;j<10;j++);}}//名称: 1602忙检测函数void lcd_wait_busy(void){TRISD7=1; //为读状态做准备,把RD7设为输入RSPIN=0; //选择指令寄存器RWPIN=1; //选择读EPIN=1; //使能线电平变动while(RD7==1); //读忙状态,不忙时退出EPIN=0; //恢复使能线电平TRISD7=0; //把RD7设置为输出}//名称: 1602写命令函数void lcd_write_com(unsigned char combuf){RSPIN=0; //选择指令寄存器RWPIN=0; //选择写PORTD=combuf; //把命令字送入RDEPIN=1; //使能线电平变动,命令送入1602的8位数据口asm("NOP"); //来一个空把持,以延时片刻EPIN=0; //恢复使能线电平}//1602写命令函数(带忙检测)void lcd_write_com_busy(unsigned char combuf){lcd_wait_busy();//调用忙检测函数lcd_write_com(combuf); //调用写命令函数}//1602写数据函数(带忙检测)void lcd_write_data(unsigned char databuf){lcd_wait_busy();//调用忙检测函数RSPIN=1; //选择数据寄存器RWPIN=0; //选择写PORTD=databuf; //把数据字送入RD口EPIN=1; //使能线电平变动,命令送入1602的8位数据口asm("NOP");EPIN=0; //恢复使能线电平}//名称: 1602显示地址写函数void lcd_write_address(unsigned char x,unsigned char y){x&=0x0f;//列地址限制在0-15y&=0x01;//行地址限制在0-1if(y==0x00)lcd_write_com_busy(x|0x80); //第一行的列地址写入elselcd_write_com_busy((x+0x40)|0x80); //第二行的列地址写入}//名称: 1602初始化函数void lcdreset(void){delay1(150);lcd_write_com(0x38);delay1(50);lcd_write_com(0x38);delay1(50);lcd_write_com(0x38);lcd_write_com_busy(0x38); //8位数据,双列,5*7字形lcd_write_com_busy(0x08);//显示功能关,无光标lcd_write_com_busy(0x01);//清屏指令lcd_write_com_busy(0x06);//写入新的数据后,光标右移,显示屏不移动lcd_write_com_busy(0x0c);//显示功能开,无光标,}//指定地址写入函数void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf){lcd_write_address(x,y); //写入地址lcd_write_data(buf);//写入显示数据}/*********************************************************************/ //T0初始化函数void timer0init(void){T0CS=0; //TMR0工作于按时器方式PSA=1; //TMR0不分频TMR0IF=0; //清除TMR0中断标识表记标帜TMR0IE=1; //TMR0中断允许T0CON=0x88; //16bit按时方式,预分频关闭,TMR0H=(65536-50000)/256; //0.05;TMR0L=(65536-50000)%256;//GIE=1;}//T0中断函数 //外部中断INT处置函数 //PIC单片机和51单片机纷歧样,它只能有一个中断服务函数.void interrupt ISR(void){if(TMR0IF==1) //250us{//TMR0=0xff13; //晶振4.0M,按时250usTMR0H=(65536-50000)/256; //0.05;TMR0L=(65536-50000)%256;TMR0IF=0;a++;if(a==20){a=0;b++;if(b==999){b=0;}c++;}}if(INT0IF==1) //如果是外部中断{INT0IF=0; //清中断标识表记标帜位if(IntNum==0) KeyV=0; //接收开始,将缓冲区清零if((IntNum>0)&&(IntNum<9)) //接收8位有效码{KeyV=KeyV>>1; //因键盘数据是低>>高,结合上一句所以右移一位if (Key_Data) KeyV=KeyV|0x80; //当键盘数据线为1时为1到最高位}IntNum++; //中断次数计次if (IntNum > 10){IntNum = 0; //傍边断11次后暗示一帧数据收完,清变量准备下一次接收bf = 1; //接收完成标识表记标帜位,写1后,暗示接收OKkeybuf=KeyV; //把接收缓冲区的数据移植keybufKeyV=0; //接收缓冲区清0}}}/****************************************************************************/ /***************************************************************************/ //PS2解码处置函数unsigned char Decode(unsigned char ScanCode)//注意:如SHIFT+G为12H 34H F0H 34H F0H 12H?//也就是说shift的通码+G的通码+shift的断码+G的断码{unsigned char TempCyc;unsigned char KeyChar=0; if (!Key_UP) //当键盘松开时。

实验八 IIC通信协议

实验八 IIC通信协议

实验八I2C通信协议一、实验目的:1、培养学生阅读资料的能力;2、加深学生对I2C总线通信协议的理解;3、加强学生对模块化编程的理解;二、实验环境:1、硬件环境:PC机一台、单片机实验板一块、母头串口交叉线、USB电源线;2、软件环境:keil uVision2集成开发环境;STC-ISP下载上位机软件;三、实验原理:要学会I2C通信协议的编程,关键是要看懂并掌握其时序图,理解对I2C通信协议相关子程序的实验编写。

I2C通信协议的总线时序图如下所示:I2C总线时序图I2C相关子程序的详细介绍1、起始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

2、结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

起始信号和结束信号的时序图如下所示:起始信号和结束信号的时序图起始信号的流程如下:1、SCL和SDA拉高,保持时间约为0.6us-4us;2、拉低SDA,保持时间为约为0.6us-4us;3、拉低时钟线结束信号的流程如下:1、SCL置高电平,SDA置低电平,保持时间约为0.6us-4us2、SDA拉高,保持时间约为1.2-4us;应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。

CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。

若未收到应答信号,由判断为受控单元出现故障。

应答信号的时序图如下所示:应答时序图发送时的应答信号;**********应答信号**********ACK: SETB SDA ;数据线置高SETB SCL ;时钟线置高ACALL DELAYJB SDA,$ ;等待数据线变低ACALL DELAYCLR SCL ;时钟线置低RET注意:这里如果数据线一直为高将进入死循环,所以一般我们都会在这做一个容错的处理。

具体的程序如下:ACK: MOV R4,#00HSETB SDASETB SCLLOP0: JNB SDA,LOPDJNZ R4,LOP0 ;循环255次LOP: ACALL DELCLR SCLRET接收时的应答信号ACK1: CLR SDA ;数据线置低SETB SCL ;时钟线置高NOPNOPCLR SCL ;时钟线置低SETB SDA ;数据线置高RET3、字节的发送和接收写周期时序图一字节数据发送子程序,流程如下:图6-22 发送子程序流程图(2)一字节数据接收子程序,流程如下:图6-23 接收子程序流程图7、写操作(1)字节写图6-24 字节写时序图流程如下:图6-25 字节写的流程图(2)页写图6-26 页写时序图页写流程如下:8、读操作(1)选择读图6-28 选择读时序图图6-29 NO ACK时序图(2)连续读图6-30 连续读时序图四、实验原理图:I2C总线电路图五、实验例题:例题一编写一程序,实现I2C的指定字节读写,用24C08来记录单片机复位或者开机的次数,并将复位或者开机的次数显示在数码管上。

I2C_24C02总线通信协议实例详解(附详细示波器实测波形图)

I2C_24C02总线通信协议实例详解(附详细示波器实测波形图)

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

I2C总线只有两根双向信号线:一根是数据线SDA,另一根是时钟线SCL。

I2C总线通过上拉电阻接正电源。

当总线空闲时,两根线均为高电平。

连到总线上的任一器件输出的低电平都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。

在有些情况下,可能没接上拉电阻I2C也能正常通信,但是建议读者最好接上拉电阻。

本文最后将给出有接上拉电阻和没接两种情况下的I2C通信波形,可以明显的看出来,接了上拉电阻波形更漂亮,通信也更稳定。

本文将以24C02来详细讲解I2C 协议。

因为本文的重点是讲解I2C,所以这里只简单的介绍24C02,有关24C02的更为详细的资料,读者可以查阅其数据手册,在这里就其必需的部分进行简单的讲解。

一、 AT24C02简介AT24C02是美国ATMEL公司的低功耗CMOS串行EEPROM,它是内含256×8位(2K)存储空间,具有工作电压宽(2.5~5.5V)、擦写次数多(大于10000次)、写入速度快(小于10ms)等特点。

它的典型应用电路如图1:图1 AT24C02典型应用电路图1中AT24C02的1、2、3脚是三条地址线,用于确定芯片的硬件地址。

在本文都将其接地,表示其地址为000。

第5脚SDA为串行数据输入/输出,数据通过这条双向I2C总线串行传送,第6脚SCL为串行时钟输入线。

当用单片机I/O 口模拟I2C通信时,这两个引脚可以接任意的I/O口。

SDA和SCL都需要接一个上拉电阻,其阻值一般为4.7K~10K。

第7脚是写保护引脚,可以接IO口也可以直接接地,接地就不再具有保护功能。

这里将其直接接地。

二、 I2C总线的构成及信号类型I2C总线是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。

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

常用数据传输接口

常用数据传输接口

RST
命令和控制逻辑 地址总线 31X8bit RAM
图12.6.2 DS1302结构图
❖ DS1302的控制字节
RST
SCLK I/O
1 A0 A1 A2 A3 A4 R/C 1
LSB
MSB
(a)单字节数据读时序
RST
SCLK I/O
1 A0 LSB
A1 A2 A3 A4 R/C 1 MSB
D0 D1 D2 D3 D4 D5 D6 D7
❖ DS1302的结构及工作原理
❖ DS1302工作电压为2.5V~5.5V,采用三线 接口与CPU进行同步通信,并可采用突发 方式一次传送多个字节的时钟信号或RAM 数据。DS1302内部有一个31×8的用于临 时性存放数据的RAM寄存器。DS1302是 DS1202的升级产品,与DS1202兼容,但 增加了主电源/后背电源双电源引脚,同时 提供了对后背电源进行涓细电流充电的能 力。
传输,这就需要一定的协议来对读/写数据提 出严格的时序要求,而AT89系列单片机并不 支持单线传输。因此,必须采用软件的方法 来模拟单线的协议时序。
图12.9.1 DS18B20应用原理图
12.10 小结
❖ 本章详细介绍了I2C,SPI和1-wire三种总线 的传输协议和传输过程,本章中所设计的三 个应用实例也十分实用,在很多场合都能使 用得上,比如DS1302电子表和DS18B20温 度计。若是同学们能掌握它们的设计方法, 自己设计一个简易的电子表或温度计都不再 有问题。
SCLK SS (CS)
功能 主器件数据输出,从器件数据输入 主器件数据输入,从器件数据输出
时钟信号,由主器件产生 从器件使能信号,由主器件控制
表12.5.1 SPI 的4根信号线功能表

I2C通信时序图解析

I2C通信时序图解析

I2C通信时序图解析⼀、I2C协议简介 I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被⼴泛地使⽤在系统内多个集成电路(IC)间的通讯。

关于I2C协议的更多内容,可阅读《I2C总线协议》,本博⽂主要分析I2C波形图,对于I2C的基础知识不在做介绍。

⼆、I2C协议标准代码2.1 起始信号&停⽌信号 起始信号:当 SCL 线是⾼电平时 SDA 线从⾼电平向低电平切换。

停⽌信号:当 SCL 线是⾼电平时 SDA 线由低电平向⾼电平切换。

2.1.1 起始信号代码void I2C_Start(void){I2C_SDA_High(); //SDA=1I2C_SCL_High(); //SCL=1I2C_Delay();I2C_SDA_Low();I2C_Delay();I2C_SCL_Low();I2C_Delay();}2.1.2 停⽌信号代码void I2C_Stop(void){I2C_SDA_Low();I2C_SCL_High();I2C_Delay();I2C_SDA_High();I2C_Delay();}2.2 发送⼀个字节 CPU向I2C总线设备发送⼀个字节(8bit)数据u8 I2C_SendByte(uint8_t Byte){uint8_t i;/* 先发送⾼位字节 */for(i = 0 ; i < 8 ; i++){if(Byte & 0x80){I2C_SDA_High();}else{I2C_SDA_Low();}I2C_Delay();I2C_SCL_High();I2C_Delay();I2C_SCL_Low();I2C_Delay();if(i == 7){I2C_SDA_High(); /* 释放SDA总线 */}Byte <<= 1; /* 左移⼀位 */I2C_Delay();}} 2.3 读取⼀个字节 CPU从I2C总线设备上读取⼀个字节(8bit数据)u8 I2C_ReadByte(void){uint8_t i;uint8_t value;/* 先读取最⾼位即bit7 */value = 0;for(i = 0 ; i < 8 ; i++){value <<= 1;I2C_SCL_High();I2C_Delay();if(I2C_SDA_READ()){value++;}I2C_SCL_Low();I2C_Delay();}return value;}2.4 应答2.4.1 CPU产⽣⼀个ACK信号void I2C_Ack(void){I2C_SDA_Low();I2C_Delay();I2C_SCL_High();I2C_Delay();I2C_SCL_Low();I2C_Delay();I2C_SDA_High();}2.4.2 CPU产⽣⼀个⾮ACK信号void I2C_NoAck(void){I2C_SDA_High();I2C_Delay();I2C_SCL_High();I2C_Delay();I2C_SCL_Low();I2C_Delay();}2.4.3 CPU产⽣⼀个时钟,并读取器件的ACK应答信号uint8_t I2C_WaitToAck(void){uint8_t redata;I2C_SDA_High();I2C_Delay();I2C_SCL_High();I2C_Delay();if(I2C_SDA_READ()){redata = 1;}else{redata = 0;}I2C_SCL_Low();I2C_Delay();return redata;}三、I2C通信时序图解析 有了上边的I2C总线标准代码的基础,下⾯我们进⼊本博⽂所要讲解的内容,怎么分析I2C的时序图,以O2Micro的OZ9350为例,OZ9350是⼀款模拟前端(AFE)的IC器件。

I2C操作时序问题总结(内附大量实用代码和详解)

I2C操作时序问题总结(内附大量实用代码和详解)

I2C 总线在单片机操作中用到的很多。

特别是以I2C总线进行数据和命令传输的器件,比如AT24C02存储芯片等。

特此做了相关操作过程中经常用到的操作和一些操作的解释。

相信看完之后,肯定会对I2C总线有深刻的理解。

I2C总线操作(从高位开始进行读写操作)写操作时序启动之后先进行一个字节的指令写入操作,然后进行应答;在进行字节数据的传送;然后再进行应答;I2C读操作时序基本上与写操作相同,不同的是读操作只需进行指令的写入,不写数据(应该不绝对),最后主机产生非应答信号,结束数据的读取;在对E2PROM(24C02)进行操作时,写入写操作指令后,然后写入需要操作的存储器地址号,最后写入数据。

且每个存储器地址只能赋值一次,重复对该存储器地址赋值会使前一个数据丢失。

读操作过程中需对将指令改写为读指令,在读取数据时需要写入指令指明需要读出数据时的存储器地址号下面是对24C02的写操作和读操作void write_add(uchar address,uchar date){start();write_byte(0xa0); //写指令respons();write_byte(address); //写入要操作的存储器地址respons();write_byte(date); //写入存储器数据respons();stop();}uchar read_add(uchar address){uchar date;start();write_byte(0xa0); //写入指令respons();write_byte(address); //写入读取操作时,要读取的存储器地址respons();stop();start();write_byte(0xa1); //写入指令,进行读操作respons();date=read_byte(); //进行读取数据norespons();stop();return date;}void main(){init();write_add(23,0xcc); //写入存储器地址号为23中,数据为0xcc delay1(100);P1=read_add(23); //读入存储器地址号为23中的数据,并将数据赋值给P1口,通过数码管显示while(1); //停留在此处}I2C串行总线的操作程序起始信号(时钟线为高,数据线由高变低):void AT24C04_Start(){SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时SDA = 0; //产生下降沿 Delay5us(); //延时SCL = 0; //拉低时钟线}结束信号:(时钟线为高,数据线由低变高)void AT24C04_Stop(){SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时SDA = 1; //产生上升沿 Delay5us(); //延时}字节传输:(每个字节为8位,一个字节带一个相应位)发送数据:void AT24C04_SendByte(BYTE dat){BYTE i;for (i=0; i<8; i++) //8位计数器{dat <<= 1; //移出数据的最高位SDA = CY; //送数据口SCL = 1; //拉高时钟线Delay5us(); //延时SCL = 0; //拉低时钟线,以便下一次传送数据 Delay5us(); //延时}AT24C04_RecvACK();}接收数据:BYTE AT24C04_RecvByte(){BYTE i;BYTE dat = 0;SDA = 1; //使能内部上拉,准备读取数据for (i=0; i<8; i++) //8位计数器{dat <<= 1;SCL = 1; //拉高时钟线Delay5us(); //延时dat |= SDA; //读数据SCL = 0; //拉低时钟线以便下一个数据传送 Delay5us(); //延时}return dat;数据响应:每次数据传输成功后,接收器件发送一个应答信号,当第九个信号产生时,产生应答信号的器件将SDA拉低。

I2C总线入门(很详细,很经典)

I2C总线入门(很详细,很经典)

I2C总线入门1)最近学习51单片机,学到A/DQ/A转换的时候发现我板子上的转换芯片不是书上所讲的ADC0804和DAC0832而是PCF859仃,看了一下它的数据手册, 发现它并不是书上所说的并行传输数据,是使用I2C总线传输的。

搞了两天才搞懂,写出来给大家分享一下,不足之处请务必不吝指出。

! ≡tt f Itiief II R J Ih PHiLlPSt j ΓC bFC 口対由⅞⅛⅞κΓt r SDA IUB L f W r■I. SeiL閃離找L#參G [⅛总蠻H件嗣时Mtfl ι⅛X⅛ttStM'QUIA ft/i CPU 1√ Kf?IC ZlHh IC J J Ie Z糾幣町遊i;I^I ILW*s4t∣ιIkh i P"⅛.BtflK硏是Jl伯的内评.iaiT IT K以上是I2C总线的简单介绍。

就比如说AT24C02存储芯片,和PCF8591数模模数转换芯片都支持I2C端口(如下图)2)接下来看如何使用I2C总线进行通信3. I S C总线通信格式图8,i+2 ⅛ PC总统上进彳J -次数撫传输的通信格式HJ. λ5WuJΓ IMPuJT λWλ√[T+ *1⅛∕'f ⅛ff融戟代答ftK >⅛祎:J*j*hrn⅛释止他号图S.I .2 I3C总纽上遊打谀散据传输的JfflG⅛A 以上是I2C 总线通信的格式。

由上图可以看出进行通信需要以下几个步骤S-Iead PDlPAOL1 8□ VCCAl匚⅛WPA2匚3GND匚4£AJNOITU迴VDDAINlI 2ISj AOUTAIN2 3]回” RE FAIN3 I 41^I3] AGNDPCF8591PAO ^5∏^↑2∖ EXTAt叵TrlOSCA2 T/JO)SeL^kVSS叵(VJ SDAIH2引脚图(Dlla.初始化I2C总线就是把SDA和SCL都变成高电平。

Void in it() 〃初始化{SDA=1;delay();SCL=1;delay();}delay ()为延时函数void delay() 〃延时4-5个微秒{;;}b.发送起始信号就是保持SCL为高电平,而SDA从高电平降为低电平(这是I2C总线的规定, 别问我为什么)void Start()// 起始信号{SDA=1;delay();SCL=1;delay();SDA=0;delay();}C.发送地址字(芯片的硬件地址)74地址12C总线象统中的每一片PCF859J通过发送有效地址封该黠件来激活。

第11章 I2C总线图文图文课件

第11章 I2C总线图文图文课件

编号;
位 为1,表示要对器
01
3.数据传输 在数据传送过程中,SCL为高电平时,SDA必须是一稳定的高或低电平,此时
数据有效。SDA线的改变只能发生在SCL为低电平。 4.传输应答
所有数据都是按字节发送的,每次发送的字节数不限,但每发完每一个字节 要释放SDA线(呈高电平),然后由接收器下拉SDA线(呈低电平)产生应答位,表 示传输成功,此时主控器必须产生一个与此位相应的额外时钟脉冲。I2C 总线 数据传送时,每成功地传送一个字节数据后接收器都必须产生一个应答信号, 应答的器件在第9 个时钟周期时将SDA 线拉低,表示其已收到一个8 位数, 24C04在接收到起始信号和从器件地址之后响应一个应答信号,如果器件已选择 了写操作,则在每接收一个8 位字节之后响应一个应答信号。当24C04 工作于
主机发送地址时,总线上的每一个从机都将这7位地址码与自已的器件地址 进行比较,如果相同则认为自已正被主机寻址,根据读写位将自已确定为发送 器或接收器。
从机的地址由一个固定部分和一个可编程部分组成。固定部分为器件的编号
02 例如24C02的地址格式如下:
其中高四位1010为器件标识类型。 A2~A0:引脚地址,对应于该芯片引脚A2~A0的取值,当A2-A0引脚均接低电 平时,该器件的地址为A0H或A1H,如果为A0H表示写数据到该器件,A1H表示从 该器件读数据。 说明:从机地址只表明选择挂在总线的哪一个器件及传送方向,而器件内 部的地址是由编程者传送的第一数据中指定的,即第一个数据为器件内的子地 址。
功能:该函数与rcvbyte() 不同,它包含了从启动总线、 发送从器件地址、读数据到结 束总线的全过程。
如其果中返:回1表示操作成功, 否则s操la作:有从错器。件地址
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

启动信号:
SCL为高电平的时候,SDA由高电平向低电平跳变。

结束信号:
SCL为高电平的时候,SDA由低电平向高电平跳变。

应答信号:
I2C总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。

应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功,对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。

如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

写时序:
开始信号:主机+从设备地址+写命令,从机应答,应答成功,表示有这个设备,然后主机+设备内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址,主机写入数据,从机应答,是否继续发送,不发送的话,发送停止信号P。

读时序:
要想读设备,首先要知道将要所读取设备的地址告诉从设备,从设备才能将数据放到(发送)SDA上使主设备读取,从设备将数据放入SDA上的过程,由硬件主动完成,不用人为的写入。

所以首先先写入从机地址,然后+写控制命令,从机应答,应答成功,表示有这个设备,然后写入内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址。

然后主机继续发出:写入从机地址,然后+读命令,从机应答,应答成功,此时便可以读取数据了,从设备已经将数据放入到SDA上了。

地址跟设备已经验证了,不用再进行验证。

启动信号与停止信号的时序图如下图所示:
数据位发送:
在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。

进行数据传送时,在SCL呈现高电平期间,SDA上的电平必须保持稳定,低电平为数据0,高电平为数据1。

只有在SCL为低电平期间,才允许SDA上的电平改变状态。

逻辑0的电平为低电压,而逻辑1则为高电平。

时序如下图所示:
应答信号时序图如下图所示:
当进行一次写时序的时候,SDA上的数据变化的时序图如下:
当进行一次读的时候,SDA上的数据变化的时序图如下:
i2c协议中的数据传输时序图如下:。

相关文档
最新文档