版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、目录TOC o 1-5 h z HYPERLINK l bookmark4I2C总线概述:2 HYPERLINK l bookmark6I2C要点:2 HYPERLINK l bookmark81)设备与器件:2 HYPERLINK l bookmark102)时序控制:2 HYPERLINK l bookmark123)硬件I2C使用(ARMcortexM3)4 HYPERLINK l bookmark144)软件模拟I2C5 HYPERLINK l bookmark165)I2C死锁问题5 HYPERLINK l bookmark186)I2C读写操作6 HYPERLINK l bookm
2、ark207)模拟I2C代码编写过程7 HYPERLINK l bookmark228)附件(模拟I2C代码)9I2C总线概述:1、只要求两条总线线路:一条串行数据线SDA,条串行时钟线SCL;2、每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;3、它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;4、串行的8位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;5、连接到相同总线的IC数量只受到总线
3、的最大电容400pF限制。I2C要点:1)设备与器件:主设备(master):一般为芯片的MCU(如cortexM3);从设备(slave):般是挂在I2C总线上的器件,女nE2PR0M,ADC(MAX11604).flash等外设;发送器(sender):发送数据到I2C总线上的器件;(master般发送CMD,slave般返回master请求的数据)接收器(receiver):从I2C总线上接收数据的器件;典型的I2C总线控制过程:I2C总线(主从I2C总线(主-I2C总线(主从I2C总线(主-从)SlavereceiverSlavesender2)时序控制:i.I2C的时钟线SCL永远由
4、主设备控制,从设备的时钟根据主设备的SCL自动设置(由I2C硬件控制器来完成,从设备的时钟不需要软件“干预”);ii起始、停止条件(H:高电平L:低电平)起始条件停止条件起始条件停止条件起始条件:在SCL维持高电平期间,SDA由高电平变成低电平;SDA:H-LSCL:H-H停止条件:在SCL维持高电平期间,SDA由低电平变成高电平;SDA:L-HSCL:H-HTips:起始和停止条件产生的前提,是SCL保持高电平;另在I2C总线协议中高电平表示空闲状态,因此在停止条件产生后,通过拉高SDA和SCL线来使得I2C总线处于空闲状杰.同时,起始条件产生的前提是SDA和SCL线均处于空闲状态(高电平)
5、,否则总线忙.iii应答响应(ACK、NON.ACK)SDASCLMSBAcknowledgementAcknowledgementSignalFromReceiver匚;一1SignalFromReceiverSCLMSBAcknowledgementAcknowledgementSignalFromReceiver匚;一1SignalFromReceiverIk/VySTART12789CondHion(S)叭ACKSignalFromReceiver89STOPACKCondition(P)在主设备寻址从设备时(或SETUP.CONFIG等CMD),从设备发送ACK.通知主设备寻址成功,
6、主设备控制I2C总线(拉低SCL),开始建立数据的传输。b、在I2C的数据传输中,接收者需要发送ACK(或NON_ACK)给发送者,以通知发送者是否继续数据的传输。对于b情况,一般是从设备发送主设备请求的数据到I2C总线上,如果主设备希望从设备继续发送数据,则在第九个时钟发送响应ACK(拉低SCL);如果主设备希望结束本次数据的传输,则发送NON_ACK(置高),从设备检测到NON_ACK信号(检测由I2C控制器完成),结束数据的传输。iv.从设备地址从设备的地址编址方式有7bit和lObit;1r71181r811SSlaveAddressR/WACKDataACKDataACKP1r711
7、8-11r7118111SSlaveAddressFVWACKDataACKSSlaveAddressR/WACKDataACKPl1AnyNumberNumbers:起始条件P:停止条件SlaveAddress:7bit从设备地址R/W:读写bitACK:应答响应bitData:SETUP,CONFIG等CMD(主-从)数据(从-主)有些从设备在出厂的时候,其地址9已经被固定了(如MAX11604),有些则可以根据某个bit来设置不同的地址(如E2PR0M的A0位)。对于前者,如果需要2块一样的从设备(如MAX11604),那么一个I2C总线不能寻址该从设备(因为2个从设备的地址一样),这时
8、从设备需要分别挂在2个不同的I2C总线上;对于后者9很方便,只需要给设置A0来片选即可。3)硬件I2C使用(ARMcortexM3)在硬件I2C使用中,需要注意2点:a、为了产生一个停止或者重起始条件,必须在读倒数第二个数据字节之后,设置STOP/START位。b、对于某些从设备完成某种功能时,需要拉长时钟线,以等待其完成该功能后,把数据发送到I2C总线上。(如AD模块往往需要时间采样电压,再将其采样的电压值通过AD模块内部的移位寄存器将电压值输出到FIFO缓冲,最后发送到I2C总线上。)至于需要拉长时钟线多长时间由从设备决定(参考datasheet说明)。C、当Master速度过快Slave
9、端来不及处理时,Slave设备可以拉低SCL不放(SCL=O将发生线与)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。软件模拟I2C软件模拟I2C主要涉及SCL的时钟设置,SCL决定I2CSpeed;SCL时钟的控制虽然是主设备控制的,但在模拟的情况下,SCL的时钟需要根据从设备datasheet的I2C时序要求来设置。这个和所有的外设器件一样,都有自己的工作时序要求。一般按照从设备的时序要求来控制SCL即可。I2C死锁问题在正常情况下,I2C总线协议能够保证总线正常的读写操作。但是,当I2C主设备异常复位时(看门狗动作,板上电源异常导致复位芯片动作,手动按钮复
10、位等等)有可能导致I2C总线死锁产生。下面详细说明一下总线死锁产生的原因。在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位,SCL就会被释放为高电平.此时,如果从设备没有复位,就会继续I2C的应答,将SDA直拉为低电平,直到SCL变为低电平,才会结束应答信号.而对于I2C主设备来说复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电平。这样,I2C主设备等待从设备释放SDA信号,而同时
11、I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种死锁状态.同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状态。方法尽量选用带复位输人的I2C从器件。将所有的从I2C设备的电源连接在一起,通过M0S管连接到主电源,而M0S管的导通关断由I2C主设备来实现。在I2C从设备设计看门狗的功能。在I2C主设备中增加I2C总线恢复程序。每次I2C主设备复位后,如果检测到SDA数据线被拉低,则控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况,9个
12、elk可以激活的方法来自NXP的文档,NXP(Philips)作为I2C总线的鼻祖,这样的说法是可信的),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。这种方法有很大的局限性,因为大部分主设备的I2C模块由内置的硬件电路来实现,软件并不能够直接控制SCL信号模拟产生需要时钟脉冲。或者,发送l2C_Stop条件也能让从设备释放总线。如果是GPIO模拟I2C总线实现,那么在I2C操作之前,加入I2C总线状态检测l2C_Probe,如果总线被占用,则可尝试恢复总线,待总线释放后,再进行操作。要保证I2C操作最小单元的完整性,不被其他事件(中断、高优先级线程,等)打断。在I2C总线上
13、增加一个额外的总线恢复设备。这个设备监视I2C总线.当设备检测到SDA信号被拉低超过指定时间时,就在SCL总线上产生9个时钟脉冲,使I2C从设备完成读操作,从死锁状态上恢复出来。总线恢复设备需要有具有编程功能,一般可以用单片机或CPLD实现这一功能。在I2C上串人一个具有死锁恢复的I2C缓冲器,如Linear公司的LTC4307是一个双向的I2C总线缓冲器,并且具有I2C总线死锁恢复的功能。LTC4307总线输入侧连接主设备,总线输出侧连接所有从设备。当LTC4307检测到输出侧SDA或SCL信号被拉低30ms时,就自动断开I2C总线输入侧与输出侧的连接.并且在输出侧SCL信号上产生16个时钟
14、脉冲来释放总线。当总线成功恢复后,LTC4307会再次连接输入输出侧,使总线能够正常工作。I2C读写操作一般情况下都是I2C的主设备(MCU)读取从设备(如AD)的值.而大多数的从设备都是需要设置其工作模式,即配置从设备。因此在读取从设备之前,必须先发送配置从设备工作模式的CMD.所以读从设备往往需要先写从设备(写控制从设备工作模式的CMD)。例如MAX11604的ADC模块,MCU(cortexM3)要读取AD转换的电压值,必须先配置AD工作的模式和采用的通道。因此读取ADC的操作包含了2个写操作,分别是写SETUP命令和CONFIG命令。之后才开始发送读bit,开始读取AD转换的电压值。模
15、拟I2C代码编写过程a、模拟I2C原因:MAX11604是一个8位12路AD,其地址在出厂的时候9已经固定死了。在开发的项目中需要AD采样24路信号,即需要2块AD.问题来了,2块AD芯片的地址一样,不能够同时挂在一条I2C总线上。因此必需使用2条I2C总线。开发的硬件平台恰好有2个硬件I2C控制器,但其中一个被网口给占用了(即网口Mil和其中一个I2C复用)。如此一来,不得不模拟一个I2C总线.b、I2C模块化设计模拟2条I2C总线,大部分的代码相同,唯一不同的是使用的GPIO口管脚不一样。为了减少代码的重复和臃肿,提高代码的重用性,采用模块化设计的思想。因此很多之前写gpio管脚的宏操作(
16、SDA_H、SDA_L、SDA_OUT、SDAJN等宏)必需重写。由于这些需要重写的宏操作都是与GPIO管脚相关的,因此需要把GPIO口管脚作为参数传递给需要重写的宏操作但宏定义是在预编译的时候确定的,而具体管脚的确定却是根据程序的运行来确定的。所以不能使用宏,最终改写成带参数函数形式。这些宏操作的代码较短,为了提高性能,减少函数的堆栈调用,全部改写成带参数的内联函数。女口:staticinlinevoidSCL_SET(sl2C*I2C_xzu8level)if(level)(I2C_XSCL_PORT卜BSRR=l2C_xSCLPin;else(I2C_XSCL_PORT)BRR=l2C_
17、xSCLPin;c、针对前面的情况,也可以把这些需要重写的宏定义和GPIO口,封装在一个结构体中。如typedefstructGPIO_TypeDef*GPIOTypeDef*ul6SCL_PORT;SDA_PORT;SCLPin;ul6SDAPin;u32SCL_CLK;u32SDA_CLK;(void)(*SDA_IN)(void)SDAJN;(void)(*SDA_OUT)(void)SDA_OUT;sl2C;这样只需要调用l2C_x-SDA_0UT即可,有点类似于C+中的类成员函数的调用。但这种方法并不是最好的。首先,针对不同的模拟I2C,需要编写不同的结构体成员函数的具体实现。(如S
18、DA1_IN()/SDA2_IN();其次,这种封装的方法并没有充分利用模块化的SDAJN()等内联函数,违背了模块化设计的初衷,模块化的抽象函数不应该放在封装的结构体中。因此定义的I2C结构体只应该包含其对应的GPIO口及其管脚如typedefstructGPIO_TypeDef*GPIOTypeDef*ul6ul6u32u32SCL_PORT;SDA_PORT;SCLPin;SDAPin;SCL_CLK;SDA_CLK;sl2C;而抽象出来的重写的内联函数SDAJN等作为独立的外部函数。同时为了减少结构体的参数的复制,采用传指针的形式来传递I2C结构体,大大减少结构体的copy”另外把st
19、aticvoidSCL_SET(sl2C*I2C_x,u8level)等函数,改写成内联inline函数的形式,进一步减少函数调用的开销。这样在调用这些内联函数的地方,相当于宏的展开。但要注意不能滥用内联函数,一般只有极少几行代码的函数才会选择使用内联函数的形式。(对于某些编译潯,如果某个函数的实现只有1、2行时,即使没有显式写成内联函数,在编译器编译的时候,也会自动编译成内联函数)。8)附件(模拟I2C代码)i.i2c.h文件ffifndefI2CHffdefineI2CH/include,stm32flOx.h/*simulatesi2ctimingspeed,6unitasoneeye*
20、/ffdefineI2C_SPEED_6(100*1000)/defineH1#defineLOpp*拿拿車水*拿車水*拿$I2Cj*BSRR=I2C1_SDA_PIN;I2C1_SDA_PORTBSRR=I2C1_SCL_PIN;I2C2_SCL_PORTBSRR=I2C2_SDA_PIN;I2C2_SDA_PORTBSRR=I2C2_SCL_PIN;voidi2cjnit(void)ffifdefSIMU2C_TESTledjnit();ffendifi2c_gpio_init();i2c_idle_set();/seti2cbustoidleu8i2c_start(sl2C*I2C_x)
21、SDA_FUNC(I2C_X,SDA_OUT);SDA_SET(I2C_X,H);SCL_SET(l2C_x,H);delay_us(4);/delaytimeforrestartconditionif(!SDA_READ(l2C_x)return0;/ifI2Cbusbusy,return;SDA_SET(l2C_x,L);delay_us(4);SCL_SET(l2C_x,L);/holdonscl,standbytransssiondelay_us(l);return1;voidi2c_stop(sl2C*I2C_x)SDA_FUNC(I2C_X,SDA_OUT);SCL_SET(l2C
22、_x,L);SDA_SET(l2C_x,L);delay_us(4);SCL_SET(l2C_x,H);delay_us(l);SDA_SET(I2C_X,H);delay_us(4);/*waitack:masterreveicerwaittheslavesenderacksucceed:return1failed:halt!7voidi2c_wait_ack2C拿l2C_x)ul6uErrTime=0;SDA_SET(l2C_x,H);/freesdabusSDA_FUNC(l2C_x,SDA_OUT);/settorecevierdelay_us(l);SCL_SET(l2C_x,H);
23、delay_us(l);while(SDA_READ(l2C_x)/getackstatus,ifnonack(HIGH_LEVEL)wait250fclkuErrTime+;if(uErrTime2500)/timeout,receivefailedi2c_stop(l2C_x);/stoptransferwait_ack_timeout();ffifdefSIMUJ2C_TESTled_spark();ffendifSCL_SET(l2C_x,L);/holdonSCLgotothewaitingmode/attheninthtimeclockcycle(SCL:LHL),theack_e
24、rmustholddownSDAbusifack7voidi2c_ack(sl2C*I2C_x)SCL_SET(I2C_X,L);SDA_FUNC(I2C_X,SDA_OUT);SDA_SET(l2C_x,L);/ackwithLOW-LEVELdelay_us(2);SCL_SET(I2C_X,H);delay_us(2);SCL_SET(I2C_X,L);voidi2c_non_ack(sl2C*I2C_x)SCL_SET(I2C_X,L);SDA_FUNC(I2C_X,SDA_OUT);SDA_SET(l2C_x,H);/nonackwithHIGH_LEVELdelay_us(2);S
25、CL_SET(I2C_X,H);delay_us(2);SCL_SET(I2C_X,L);广send1bytetothereveivereachperiod:(2+2+2广lOus7voidi2c_sendbyte(sl2C*I2C_x,u8sendbyte)u8i=8;SDA_FUNC(I2C_X,SDA_OUT);SCL_SET(I2C_X,L);while(i-)/sendHIGHbitfristif(sendbyte&0 x80)SDA_SET(I2C_X,H);elseSDA_SET(I2C_X,L);sendbyte=1;delay_us(2);/waitnthlevelsetup
26、SCL_SET(l2C_x,H);/generateSDAleveldelay_us(2);/SCLhighlevelholdtimeSCL_SET(l2C_x,L);/finishgeneratedelay_us(2);/holdonSCLffifdefSIMU2C_TESTffifdefLED_ONif(SDA_READ(l2C_x)GPIO_SetBits(GPIOA,GPIO_Pin_7);elseGPIO_ResetBits(GPIOA,GPIO_Pin_7);delay_us(2);ffendif/endifLED_ONffendif/*read1bytefromthesender
27、*/u8i2c_readbyte(sl2C*I2C_xzu8ack)u8i=8;u8receive_byte=0;SDA_FUNC(l2C_x,SDAJN);/settoreceiverwhile(i-)receive_byte=1;SCL_SET(l2C_x,L);delay_us(2);SCL_SET(l2C_x,H);/startsamplingSDAdelay_us(2);/samplingholdtime,inT_HIGHtheSDAcantchangethelevel严ifhighlevelwritelfotherwisewrite0*/if(SDA_READ(l2C_x)rece
28、ive_byte|=0 x01;if(ack)i2c_ack(l2C_x);else/whenthereceiverisamaster,sendanonacktoendthetransferi2c_non_ack(l2C_x);returnreceive_byte;广func_status:in/outputSDAJN:CRx_MODE_IN_PULL(0 x08)SDA_OUT:CRx_MODE_OUT_10M(0 x01)7staticinlinevoidSDA_FUNC(sl2Cl2C_x,u32func_status)if(POS(l2C_x-SDAPin)SDA_PORT)CRL&二
29、CRL_BITx_MASK(l2C_xSDAPin);(I2C_XSDA_PORT)CRL|=(funcstatus(4*POS(l2C_xSDAPin);else/pin:8-15(CRH)(I2C_XSDA_PORT)CRH&二CRL_BITx_MASK(l2C_xSDAPin);(I2C_XSDA_PORT)CRH|=(func_status(4(POS(l2C_x-SDAPin)%8);广HIGH_LEVEL:1LOW_LEVEL:07staticinlinevoidSCL_SET(sl2C*I2C_xzu8level)if(level)(I2C_XSCL_PORT)BSRR=l2C_
30、x-SCLPin;else(I2C_XSCL_PORT)BRR=l2C_x-SCLPin;staticinlinevoidSDA_SET(sl2C*I2C_x,u8level)if(level)(I2C_XSDA_PORT)BSRR=l2C_x-SDAPin;else(I2C_XSDA_PORT)BRR=l2C_x-SDAPin;staticinlineul6SDA_READ(sl2C*I2C_x)return(l2C_x-SDA_P0RT)IDR&l2C_xSDAPin);staticvoidwait_ack_timeout(void)printf(,ntttwaitack(fromslav
31、e)timeout,systemhalt!nM);while(1);iii.Max_11604.h文件include,stm32flOx.h,include,i2c.hHincludeusart-h1includedelay.h“includestdio.h#ifdefDEBUG/debug井definePDEBUG()printf(_VA_ARGS_)井else井definePDEBUG(.)ffendifdefineADC_WRITE_CMD0 x00defineADC_READ_CMD0 x01defineADC_SLAVE_ADDR0 x65/0bll00101(7bit);MAX11
32、604datasheet,page12/*HSmodemastercode0000lxxx,thenissuesanotack,allowingSDApulledhighsclforoneclkz*afthernotack,themastermustsendarepeatesstartcondition,elsewillresettofastmodeauto/defineHIGH_SPEED_MODE0 x080/defaultmode:fastmode/ADconverttimedefine(maxll604page2)/defineT_CONVNTER_CLK6/max6.1usdefin
33、eT_CONV_EXTER_CLK5/min4.7us/*setupmode(page11,tabl)*/defineSETUP_MODE(u8)0 x017)/MSBwithl:setupbyteformatdefineEXTERNAL_CLK(u8)0 x013)defineINTERNAL_CLK(u8)0 x003)/defaultelkwhenpower-updefineBIPOLAR(u8)0 x012)defineUNIPOLAR(u8)0 x002)/defaultpolarwhenpower-updefineSEL_x(0 x074)/seibit4-6/*configure
34、mode(page15,tab2)*/defineCONFIG_MODE(u8)0 x007)/MSBwith0:configurebyteformatdefineSIG_ENDED(u8)0 x01)/insingle-endedmode,maxll604awlaysoperateinunipolarmodewhateverthebip/unisettingdefinePSEUDO_DIFF(u8)0 x00)/inputvoltagefrom-128to+128/*scanmodetable(page17,tab3)*/defineSCAN_AIN0_AINx0 x00/scan0scan
35、l(0b00):scanupAINOfromAINxwhichselectedbycs0-cs3井defineSCAN_AINx_8T0 x01/scanO-scanl(ObOl):theconversionchannelthatselectedbycs3-csO8times井defineSCAN_AIN6_AINx0 x02/scanO-scanl(OblO):scanupfromAIN6toAINxwhichselectedbycsO-cs3井defineSCAN_AINx0 x03/scanO-scanl(Obll):conversionchannelselectedbycsO-cs3/
36、*channelselected*/井defineCS(x)(x)1)/eg:CS(10),meansetcsO-cs3to1010,channelAIN10beingselecteddefineSCAN_AIN(x)(x)5)/*setupcmdandconfigurecmd*/defineSETUP_CMD(SETUP_MODE|INTERNAL_CLK|UNIPOLAR|SEL_x)井defineCONFIG_CMD_DEF(CONFIG_MODE|SIG_ENDED|SCAN_AIN(SCAN_AINx)|CS(10)/setchannel10tothedefalutconfigure
37、mode/*markconfigurecmd*/井defineMARK_CONFIG_CMD_DEF(ain)(CONFIG_MODE|SIG_ENDED|SCAN_AIN(SCAN_AINx)|CS(ain)井defineMARK_CONFIG_CMD(mode,ain)(CONFIG_MODE|SIG_ENDED|SCAN_AIN(mode)|CS(ain)/*definitionoftimingdelayforSDA/SCLbaseonMAX11604datasheet/井defineT_Sr_SETUP1/Minsetuptimeforarepeatedstartcondition(S
38、r):0.6us井defineT_HD_STA1/Minstartholdtime:0.6us井defineT_LOW2/Minclockpulsewidthlow:1.3us井defineT_HIGH1/Minclockpulsewidthhigh:0.6us井defineT_BUF5/timethebusmustbefreebeforeanewtransmissionstart,atleat4.7us井defineT_SU_STOP5/stopsetuptime,atleat4.7usdefineT_SDA_H仃_HIGH+(T_R+T_F)/2)defineT_ACQ2/*timeout
39、foreventcheck*/井defineADC_FLAG_TIMEOUT(u32)0 xl000)井defineADC_LONG_TIMEOUT(10*ADC_FLAG_TIMEOUT)defineNON_ACK0defineACK1/*relocationfputcthetheUSART*/definePUTCHAR_PROTOTYPEintfputc(intchzFILE*f)/*MAX11604opsfunc*/voidl2C_ADC_lnit(void);floatl2C_ADC_Read(u8adc_no,u8cs_channel);井endifiv.Max_11604.c文件井
40、include,max_11604.hH井defineSAMPLING_TIMES50井defineREFERENCE_VALUE3.3fvu32adc_timeout=0;floatADC_ConvertVal_BuffSAMPLING_TIMES;/*defineI2C_1andI2C_27sl2Cl2C_x=I2C1_SCL_PORI;I2C1_SDA_PORI2C1_SCL_PIN,I2C1_SDA_PIN,I2C1_SCL_CLK,I2C1_SDA_CLK,I2C2_SCL_PORI;I2C2_SDA_PORI2C2_SCL_PIN,I2C2_SDA_PIN,I2C2_SCL_CLK
41、,I2C2_SDA_CLK,;staticvoidmax_adc_setup(sl2C*xJ2C);staticvoidmax_adc_config(sl2CT2C_x,u8cs_channel);staticinlinevoidi2c_send7bit_addr(sl2Cx_I2C,u8addr,u8adc_cmd);staticu8read_max_adc(sl2CF2C_x);staticvoidadc_timeout_callback(void);staticfloatget_voltg(u8convert_val);staticfloatget_average(float*pconv
42、ert_val/u8len);折fdefSIMU2C_TESTstaticvoidcheck_i2c_timing(void);#endifvoidl2C_ADC_lnit(void)usartjnit();i2cjnit();ifdefSIMU2C_TESTcheckJ2c_timing();#endifmax_adc_setup(&I2C_x0);max_adc_setup(&I2C_x);staticvoidmax_adc_setup(sl2C*I2C_x)PDEBUG(ntttmaxadcsetup.nH);/ifi2cbusbusy,waitunitllbusidle*/adcjim
43、eout=ADC_LONG_TIMEOUT;while(!i2c_start(l2C_x)if(adc_timeout-)=0)/iftimeoutadc_timeout_callback();/goingoncallbackfunc,haltupsystem严send7bitslaveaddressforwrite/i2c_send7bit_addr(l2C_x,ADC_SLAVE_ADDR,ADC_WRITE_CMD);i2c_wait_ack(12C_x);/setupmaxll604workingmode*/i2c_sendbyte(l2C_x,SETUP_CMD);i2c_wait_
44、ack(12C_x);i2c_stop(l2C_x);scan_mode:00/01/10/ll(scan-scanl)cs_set:channel0-ll(cs0-cs3)/staticvoidmax_adc_config(sl2C拿l2C_x,u8cs_channel)adcjimeout=ADC_FLAG_TIMEOUT;while(!i2c_start(l2C_x)if(adc_timeout-)=0)adc_timeout_callback();严send7bitslaveaddressforwrite*/i2c_send7bit_addr(l2C_x,ADC_SLAVE_ADDR,
45、ADC_WRITE_CMD);i2c_wait_ack(12C_x);i2c_sendbyte(l2C_x,MARK_CONFIG_CMD(SCAN_AINx,cs_channel);i2c_wait_ack(12C_x);i2c_stop(l2C_x);/*readmaxll604adc,gettheconversionvalue/staticu8read_max_adc(sl2C*I2C_x)uint8_tADC_ConvertVal;adcjimeout=ADC_FLAG_TIMEOUT;while(!i2c_start(l2C_x)if(adc_timeout-)=0)adc_time
46、out_callback();i2c_send7bit_addr(l2C_x,ADC_SLAVE_ADDR,ADC_READ_CMD);i2c_wait_ack(12C_x);i2c_clock_stretch();/holddownscl,waitADconversionfinishADC_ConvertVal=i2c_readbyte(l2C_x/NON_ACK);i2c_stop(l2C_x);returnADC_ConvertVal;staticinlinevoidi2c_send7bit_addr2C拿l2C_x,u8slave_addr,u8adc_cmd)PDEBUG(Mnttt
47、command:%dnJadc_cmd);i2c_sendbyte(l2C_x,(slave_addr1)|adc_cmd);staticvoidadc_timeout_callback(void)printffXnI2Cbusisbusy,pleasetrylater!nn);while(1);floatl2C_ADC_Read(u8adc_no,u8cs_channel)inti=0;inttemp_convert_val=0;floataverage_samp_val=0;max_adc_config(&l2C_xadc_no-lLcs_channel);/*MAX_ADCisready,startconversion/for(i=0;iSAMPLING_TIMES;+i)temp_convert_val=read_max_adc(&l2C_xadc_no-l);ADC_ConvertVal_Buffi=get_voltg(temp_convert_val);printf(HADC_CnvertVal%d=%fn,/i,ADC_ConvertVal_Buffi);average_samp_v
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 医疗数据安全人才校企联合培养模式
- 胃肠镜知识教学课件
- 甘肃省白银市靖远第一中学2026届语文高三第一学期期末统考模拟试题含解析
- 医疗数据存储的区块链安全技术创新
- 医疗数据匿名化技术的伦理边界与质量保障
- 医疗数据区块链完整性技术未来趋势研判
- 湖南省长沙市岳麓区湖南师大附中2026届高二上生物期末复习检测模拟试题含解析
- 医疗数据共享的安全保障升级
- 福建省百所重点校2026届数学高三第一学期期末检测模拟试题含解析
- 医疗数据共享安全:区块链与智能合约审计
- 【八年级上册地理】一课一练2.2 世界的气候类型 同步练习
- 2024人形机器人产业半年研究报告
- 筋膜刀的临床应用
- 生物医学分析化学方程式总结
- 中国石化《炼油工艺防腐蚀管理规定》实施细则(最终版)
- 家庭系统疗法
- JCT640-2010 顶进施工法用钢筋混凝土排水管
- 四川省遂宁市2024届高三上学期零诊考试高三生物答案
- GB/T 70.3-2023降低承载能力内六角沉头螺钉
- 锅炉焊接工艺规程
- fy17起搏器销售-t10t20说明书ifu pacetchinese livetec
评论
0/150
提交评论