Linux设备驱动第十二天(I2C下)

回顾:
1. linux内核的分离思想
分离硬件和软件
struct platform_device:装载硬件信息
.name 用于匹配
.id 如果有多个,通过id编号
.resource 装载硬件信息
.start
.end
.flags
IORESOURCE_MEM
IORSOURCE_IRQ
.num_resources 资源个数
.dev = {//自己定义的硬件信息
.platform_data 装载硬件信息
}

 struct   platform_driver:装载软件信息
 .driver ={
       .name 用于匹配
 }
 .probe 匹配成功,内核调用
 .remove 卸载,内核调用

注意:probe函数是否被内核调用很重要!!如果未调用,说明软件、硬件没有完全结合!!
注意:以上驱动的编程方法适合于所有设备!!
2. I2C 总线
概念:两线式串行总线
SCL:时钟控制信号线,控制双方的数据传输过程
SDA:数据线,传输数据
串行:一个时钟周期传输一个bit行!
总线:在I2C总线可以挂接很多设备!
上拉电阻:两个信号线的电平默认是高电平!

slave:
master:
MSB:
LSB:
I2C总线一次传输一个字节,如果是四个字节的数据要分四次传。
从高位开始传输!!

问:CPU是如何定位在I2C 总线上某个外设备?
问:CPU如何通过两根信号线和外设进行数据交互?
问:SDA和SCL如何配合使用?
答案都在I2C总线协议中!

START信号:SCL为高,SDA由高向低跳变
STOP信号:SCL为高,SDA由低向高跳变
设备地址:举例AT24C02和ADP8860为例
ACK信号:
读写信号:
读:1
写:0
ACK信号:第九个时钟周期,低电平有效

以将数据0x55写入到AT24C02的0x10地址中为例:

SDA和SCL如何配合使用呢?
例如:
CPU将某个bit位写入设备中:
1,CPU将SCL拉低(只要在低电平的过程中,都可以向数据线上放数据)
2,CPU将某个bit位的数据放在数据线上
3,CPU将SCL拉高,数据线上的数据保持稳定
4,设备在同周期的SCL为高电平,从数据线上获取数据

CPU读取设备发送来的某个bit位数据:
1,CPU将SCL拉低(让设备将数据写入到数据线上)
2,设备将数据放在数据线上
3,CPU将SCL拉高(为了让CPU自己读取数据),数据线上的数据保持稳定
4,CPU在同周期的SCL为高电平,从数据线上获取数据

总结:SCL为低电平时,SDA上的数据可以进行改变;SCL为低电平时,SDA上的数据保持稳定!

I2C 总线数据传输速度:
100K
400K
3.4M

总结:对于I2C设备的访问具体操作关键看芯片的操作时序图!!

案例:CW210开发板上有一个EEPROM(AT24C02),I2C接口,需要就是存储软件版本到AT24C02中,并且能够读取版本号从AT24C02!

软件版本号的格式:SYYMMDXY 例如 S14121700
char *p = “S14121700”;

驱动采用GPIO模拟I2C时序来实现!
了解AT24C02属于EEPROM(电可擦除存储器)
容量为256字节
工作频率:100K或者400K

可以按页进行访问:一页为8字节,共32个页。

这里写图片描述

涉及的GPIO管脚:
GPD1_0 -> SDA
GPD1_1 ->SDA

#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include <linux/workqueue.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <asm/gpio.h>
#include <linux/gpio-cfg.h>


#define DELAY(us) time_delay_us(us)

#define SCL        (1<<0)
#define SDA        (1<<1)

#define GPIO_I2C_READ      0x100001
#define GPIO_I2C_WRITE     0x100002

struct eeprom_data {
    unsigned char addr;//片内地址
    unsigned char data;//片内数据
}

static void i2c_set(unsigned whichline){
    if(whichline == SCL){
        gpio_direction_output(S5PV210_GPD(1),1); 
        return;
    }
    else if(whichline == SDA){
        gpio_direction_output(S5PV210_GPD(0),1);
        return; 
    }
    else if(whichline == (SDA|SCL)){
        gpio_direction_output(S5PV210_GPD(1),1); 
        gpio_direction_output(S5PV210_GPD(0),1);
        return; 
    }
    else{
        printk("error input.\n");
    }
}

static init gpio_i2c_init(void){
   int ret;

   ret = misc_register(&gpioi2c_dev);
   if(0!=ret)
      return -1;

   gpio_request(S5PV21_GPD1(0),"SDA0");
   gpio_request(S5PV21_GPD1(1),"SCL0");

   i2c_set(SCL|SDA);
   return 0;
}

static void gpio_i2c_exit(void){
   misc_deregister(&gpioi2c_dev);
   gpio_free(S5PV21_GPD1(0));
   gpio_free(S5PV210_GPD1(1));
}

module_init(gpio_i2c_init);
module_exit(gpio_i2c_exit);

MODULE_LICENSE("GPL");

60:17

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值