linux模拟iic代码
2016-07-04 21:33
597 查看
因2440自带的IIC控制器本人用它作为从机使用,所以用GPIO模拟了IIC总线的主机模式。以下列出驱动代码和应用试验程序
总线模拟读写EEPROM
1.底层驱动
2.应用程序
总线模拟读写EEPROM
1.底层驱动
/********************************* ** EEPROM模拟IIC总线 驱动程序 ** ** 日期:2012.8.30 ** ** 版本:V1_0 ** *********************************/ #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/wait.h> #include <linux/sched.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/delay.h> #include <mach/regs-clock.h> #include <plat/regs-timer.h> #include <plat/regs-adc.h> #include <mach/regs-gpio.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #include "s3c24xx-adc.h" static void __iomem *base_addr; #define GPJCON (*(volatile unsigned long *)(base_addr + 0)) #define GPJDAT (*(volatile unsigned long *)(base_addr + 0x04)) #define GPJUP (*(volatile unsigned long *)(base_addr + 0x08)) #define DEVICE_NAME "eeprom_micro2440_drv" static struct semaphore lock; #define I2CSDA_HIGH (GPJDAT=GPJDAT|(0x01<<4)) #define I2CSDA_LOW (GPJDAT=GPJDAT&(~(0x01<<4))) #define I2CSCL_HIGH (GPJDAT=GPJDAT|(0x01<<3)) #define I2CSCL_LOW (GPJDAT=GPJDAT&(~(0x01<<3))) #define delay_data 200 #define write_at24c32_addr 0xa0 #define read_at24c32_addr 0xa1 static void iicstart(void) { I2CSDA_HIGH; __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); I2CSDA_LOW; __udelay(delay_data); } static void iicstop(void) { I2CSDA_LOW; __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); I2CSDA_HIGH; __udelay(delay_data); } static unsigned char waitack(void) { //将SDA改为输入 GPJCON=GPJCON&(~(0x03<<8)); __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); while((GPJDAT&(0x01<<4))!=0); I2CSCL_LOW; __udelay(delay_data); GPJCON=GPJCON|(0x01<<8); I2CSDA_HIGH; __udelay(delay_data); return 1; } static void sendack(void) { I2CSDA_LOW; __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); I2CSCL_LOW; __udelay(delay_data); } static void sendnotack(void) { I2CSDA_HIGH; __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); I2CSCL_LOW; __udelay(delay_data); I2CSDA_LOW; __udelay(delay_data); } static void iicsendbyte(unsigned char ch) { unsigned char i=8; while(i--) { I2CSCL_LOW; __udelay(delay_data); if((ch&0x80)==0) { I2CSDA_LOW; } else { I2CSDA_HIGH; } ch=ch<<1; __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); } I2CSCL_LOW; __udelay(delay_data); I2CSDA_HIGH; __udelay(delay_data); } static unsigned char iicreceivebyte(void) { unsigned char i=8; unsigned char ddata=0; I2CSDA_HIGH; //将数据线改为输入 GPJCON=GPJCON&(~(0x03<<8)); __udelay(delay_data); while(i--) { ddata<<=1; I2CSCL_LOW; __udelay(delay_data); I2CSCL_HIGH; __udelay(delay_data); if((GPJDAT&(0x01<<4))==0) { ddata|=0; printk("%d=0\n",i); } else { ddata|=1; printk("%d=1\n",i); } } __udelay(delay_data); I2CSCL_LOW; __udelay(delay_data); GPJCON=GPJCON|(0x01<<8); GPJDAT=GPJDAT|(0x01<<4); __udelay(delay_data); return ddata; } static void write_at24c32(unsigned int addr,unsigned char dat) { iicstart(); __udelay(delay_data); iicsendbyte(write_at24c32_addr); __udelay(delay_data); waitack(); __udelay(delay_data); iicsendbyte((unsigned char)(addr>>8)); __udelay(delay_data); waitack(); __udelay(delay_data); iicsendbyte((unsigned char)(addr&0x00ff)); __udelay(delay_data); waitack(); iicsendbyte(dat); __udelay(delay_data); waitack(); iicstop(); __udelay(delay_data); } static unsigned char read_at24c32(unsigned int addr) { unsigned char dat=0; iicstart(); __udelay(delay_data); iicsendbyte(write_at24c32_addr); __udelay(delay_data); waitack(); __udelay(delay_data); iicsendbyte((unsigned char)(addr>>8)); __udelay(delay_data); waitack(); __udelay(delay_data); iicsendbyte((unsigned char)(addr&0x00ff)); __udelay(delay_data); waitack(); __udelay(delay_data); iicstart(); __udelay(delay_data); iicsendbyte(read_at24c32_addr); __udelay(delay_data); waitack(); __udelay(delay_data); dat=iicreceivebyte(); __udelay(delay_data); sendnotack(); __udelay(delay_data); iicstop(); __udelay(delay_data); return dat; } static ssize_t eeprom_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) { unsigned char data_temp=0; unsigned long ret=0; data_temp=read_at24c32((unsigned int)count); printk("read data_temp=%d",data_temp); ret=copy_to_user(buffer, &data_temp, 1); return ret; } static ssize_t eeprom_write(struct file *file,char *buf,size_t count,loff_t *ppos) { unsigned long ret=0; unsigned char data_temp=0; ret=copy_from_user(&data_temp,buf,1); printk("write data_temp=%d",data_temp); write_at24c32((unsigned int)count,data_temp); return ret; } static int eeprom_open(struct inode *inode,struct file *file) { //尝试打开互斥锁 int ret; ret=down_trylock(&lock); if(ret!=0) return -EBUSY; //映射IO口 base_addr=ioremap(0x560000d0,0x1c); //初始化IO口 GPJCON=GPJCON&(~(0x0f<<6)); GPJCON=GPJCON|(0x05<<6); GPJDAT=GPJDAT|(0x01<<4)|(0x01<<3); printk("eeprom init ok!\n"); return 0; } static int eeprom_close(struct inode *inodep,struct file *file) { up(&lock);//释放互斥锁 return 0; } static struct file_operations dev_fops={ .owner=THIS_MODULE, .open=eeprom_open, .release=eeprom_close, .write=eeprom_write, .read=eeprom_read, }; static struct miscdevice misc={ .name=DEVICE_NAME, .minor=MISC_DYNAMIC_MINOR, .fops=&dev_fops, }; static int __init eeprom_micro2440_init(void) { int ret; //初始化锁 init_MUTEX(&lock); //注册混杂设备 ret=misc_register(&misc); return ret; } void __exit eeprom_micro2440_exit(void) { //1.取消寄存器映射 iounmap(base_addr); //2.注销混杂设备 misc_deregister(&misc);//注销混杂设备 } MODULE_LICENSE("GPL"); MODULE_AUTHOR("xubin"); module_init(eeprom_micro2440_init); module_exit(eeprom_micro2440_exit);
2.应用程序
#include <stdio.h> #include <fcntl.h> #include <linux/types.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> int main(int argc,char **argv) { int i; unsigned char value[512]; int fd; value[0]=0x01; fd=open("/dev/eeprom_micro2440_drv",O_RDWR); if(fd<0) { printf("error\n"); exit(1); } while(1) { write(fd,value,1); printf("write reg[0]data:%x to at24lc04\n",value[0]); sleep(1); value[0]=0; read(fd,value,1); printf("read reg[0]data:%x to at24lc04\n",value[0]); value[0]+=1; } return 0; }
相关文章推荐
- Linux 进程管理
- Linux 中配置环境变量等问题
- ubuntu 64位的机器上执行arm-linux-gcc提示 no such file or directory
- comm命令
- Centos-pycharm的安装
- 每天一个linux命令(34)--top命令
- Linux 进程/端口监控 自动重启
- 安装arm-linux-gdb经验总结
- CentOS 7运维管理笔记(11)----解决配置静态IP还是会出现动态IP地址的问题
- 【实践】基于CentOS7部署Ceph集群(版本10.2.2)
- linux数值计算
- [Ceph001]基于CentOS7部署Ceph集群(版本10.2.2)
- Centos下QEMU安装
- linux多线程信号处理
- Linux查看日志命令
- Linux上安装mysql
- 转 使用putty从linux主机上面往windows主机下面拷贝文件
- Linux内核---38.S3C6410中网卡dm9000a的移植
- linux 下 sudo 指令不需要输入密码的配置
- 熟悉几个命令,脱离鼠标依赖,VIM技能升级