linux之I2C裸机驱动解析

发布时间:2024-07-19  

1 硬件特性

1.1 概述


I2C总线是由Philips公司开发的两线式串行总线,这两根线为时钟线(SCL)和双向数据线(SDA)。由于I2C总线仅需要两根线,因此在电路板上占用的空间更少,带来的问题是带宽较窄。I2C在标准模式下传输速率最高100Kb/s,在快速模式下最高可达400kb/s。属于半双工。


嵌入式系统中,I2C应用非常广泛,大多数微控制器中集成了I2C总线,一般用于和RTC,EEPROM,智能电池电路,传感器,LCD以及其他类似设备之间的通信。


1.2 I2C总线传输时序


1.3 I2C总线的信号状态


1、空闲状态:SDA和SCL都是高电平;


2、开始条件(S):SCL为高电平时,SDA由高电平向低电平跳变,开始传输数据;


3、结束条件(P):SCL为高电平时,SDA由低电平向高电平跳变,结束传输数据;


4、数据有效:在SCL的高电平期间,SDA保持稳定,数据有效。SDA的改变只能发生在SCL的低电平期间;


5、CK信号:数据传输的过程中,接收器件每接收一个字节数据要产生一个ACK信号,向发送器件发出特定的低电平脉冲,表示已经收到数据。


1.4 从设备地址


I2C总线从设备使用7位地址,最后一个为读写控制位。下图是eeprom的原理图,我们可以计算出它的地址为0x50。


1.5 I2C读写方式


多字节写的时序


多字节读的时序



具体可参考datasheet


附:ok6410裸机I2C代码。


  1 #define INTPND (*(volatile unsigned long*)0x4a000010)

  2 #define SRCPND (*(volatile unsigned long*)0x4a000000)

  3 #define INTMSK (*(volatile unsigned long*)0x4a000008)

  4 #define GPECON (*(volatile unsigned long*)0x56000040)

  5 #define GPEUP  (*(volatile unsigned long*)0x56000048)

  6 

  7 #define IICCON    (*(volatile unsigned char*)0x54000000)

  8 #define IICSTAT   (*(volatile unsigned char*)0x54000004)

  9 #define IICDS     (*(volatile unsigned char*)0x5400000C)

 10 

 11 #define SLAVE_WRITE_ADD 0xa0  /* 写入数据时;方向位(第0位)为0 */

 12 #define SLAVE_READ_ADD 0xa1   /* 读取数据时;方向位(第0位)为1 */

 13 

 14 

 15 void delay(int i)

 16 {

 17    int j = 0;

 18    while (i--)    

 19    {

 20        for (j=0;j<100;j++)

 21        {    

 22            ;

 23        }  

 24    }    

 25 }

 26 

 27 

 28 void i2c_init()

 29 {

 30     //1.a 初始化中断

 31     INTPND |= (1<<27);

 32     SRCPND |= (1<<27);  

 33     INTMSK &= ~(1<<27);

 34      

 35     IICCON |= (1<<5); 

 36     

 37     //1.b 设置scl时钟

 38     IICCON &= ~(1<<6);

 39     IICCON &= ~(0xf<<0);

 40     IICCON |= (0x5<<0);

 41     

 42     //2. 设置IICSTAT    

 43     IICCON |= (1<<4);

 44     

 45     //3.设置引脚功能

 46     GPECON |= (0x2<<28)|(0x2<<30);

 47     GPEUP |= (0x3<<14);

 48     

 49     //4.允许产生ACK

 50     IICCON |= (1<<7);

 51 }

 52 

 53 

 54 void write_byte(unsigned char xchar, unsigned char daddr)  

 55 {

 56     /* 写入数据时,每发送一个数据收到一个ACK就产生一次中断

 57      * 写入下次发送的数据之后要清除中断                      */

 58 

 59     //1. 设置处理器为主设备+发送模式

 60     IICSTAT |= (3<<6);

 61     

 62     //2. 将从设备的地址写入到IICDS寄存器

 63     IICDS = SLAVE_WRITE_ADD;

 64 

 65     //清除中断

 66     IICCON &= ~(1<<4);

 67     

 68     //3. 写入0xF0写入IICSTAT M/T Start

 69     IICSTAT = 0xF0;

 70     

 71     //4. 等待ACK的产生

 72     while ((IICCON & (1<<4)) == 0 )

 73         delay(100);

 74     

 75     //5.1写入字节的地址到IICDS寄存器

 76     IICDS = daddr;

 77 

 78 

 79     //5.2清除中断

 80      IICCON &= ~(1<<4);   

 81 

 82     //5.3等待ACK的产生

 83     while ((IICCON & (1<<4)) == 0 )

 84         delay(100);

 85     

 86     //6. 将要传输的字节数据写入IICDS寄存器

 87     IICDS = xchar;

 88 

 89     //7. 清除中断

 90     IICCON &= ~(1<<4);  

 91     

 92     //8. 等待ACk的产生

 93     while ((IICCON & (1<<4)) == 0 )

 94         delay(100);

 95     

 96     //9. 写入0xD0到IICSTAT

 97     IICSTAT = 0xD0;

 98     

 99     //10. 清除中断    

100     IICCON &= ~(1<<4);    

101     

102     delay(100);

103 }

104 

105 void read_data(unsigned char *buf, unsigned char daddr, int length) /* 结合eeprom手册 */

106 {

107     /* 每接收一个数据产生一个中断 */

108 

109     int j =0;

110     unsigned char unusedata;

111     

112     //1. 设置处理器为主设备+发送模式

113     IICSTAT |= (3<<6);

114     

115     //2. 将从设备的地址写入到IICDS寄存器

116     IICDS = SLAVE_WRITE_ADD;

117 

118     //清除中断

119     IICCON &= ~(1<<4);

120     

121     //3. 写入0xF0写入IICSTAT M/T-Start

122     IICSTAT = 0xF0;

123     

124     //4. 等待ACK的产生

125     while ((IICCON & (1<<4)) == 0 )

126         delay(100);

127     

128     //5.1写入eeprom内部地址

129     IICDS = daddr;

130 

131 

132     //5.2清除中断

133      IICCON &= ~(1<<4);   

134 

135     //5.3等待ACK的产生

136     while ((IICCON & (1<<4)) == 0 )

137         delay(100);

138 

139     /**************eeprom代码**************/

140     /**************************************/

141     /***************i2c代码****************/

142 

143     //设置为主设备接收模式

144     IICSTAT &= ~(3<<6);

145     IICSTAT |= (2<<6);

146     

147     

148     //2.写入从设备地址到IICDS  /* 从设备地址成功发送之后产生中断,故要清除中断 */

149     IICDS = SLAVE_READ_ADD;

150     //清除中断

151     IICCON &= ~(1<<4);

152     

153     

154     //3.写入0xB0到IICSTAT开始接收,每接收道一个数据就产生一个中断

155     IICSTAT = 0xb0;

156 

157     //等待中断

158     while ((IICCON & (1<<4)) == 0 )

159         delay(100);

160         

161 #if 0   

162     /***写入设备内部地址***/

163     IICDS = daddr;

164     IICCON &= ~(1 << 4);

165     while((IICCON & (1 << 4)) == 0)

166     {

167         delay(100);

168     }    

169 #endif 

170     

171     //***丢掉收到的第1个字节  第一个数据无效 丢弃!

172     unusedata = IICDS;

173     IICCON &= ~(1<<4);

174     while ((IICCON & (1<<4)) == 0 )

175             delay(100);

176     

177 

178 

179     for(j=0;j

180     {

181         if(j == (length - 1))

182         {

183            IICCON &= ~(1<<7);         

184         }

185    

186     //5.1 从IICDS里取出数据

187         buf[j]=IICDS;

188     

189     //5.2 清除中断

190         IICCON &= ~(1<<4);

191     

192     //4.等待中断

193         while ((IICCON & (1<<4)) == 0 )

194             delay(100);

195     }

196         

197         

198     //写入0x90到IICSTAT

199     IICSTAT = 0x90;

200     

201  

202     // 清除中断

203     IICCON &= ~(1<<4);

204 }

205 

206 void i2c_test()

207 {

208     int i=0;

209     unsigned char sbuf[256]={0};

210     unsigned char dbuf[256]={0};    

211     

212     i2c_init();

213     

214     for(i=0;i<256;i++)

215     {

216         sbuf[i] = i+1;

217         dbuf[i] = 0;

218     }

219     

220     printf("dbuf befor I2C read:rn");   

221     for(i =0; i<256;i++)

222     {

223        if(i%8==0)

224            printf("rn");  /*  */

225            

226        printf("%dt",dbuf[i]);    /*t-空格 */

227     }    

228      

229     for(i=0;i<256;i++)

230         write_byte(sbuf[i],i);

231         

232     printf("i2c reading, plese wait!nr");

233     

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>