微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > gpio模拟I2C

gpio模拟I2C

时间:10-02 整理:3721RD 点击:

开发中经常与i2c打交道,芯片中自带的硬件i2c控制器使用起来并不是很灵活,而且要研究半天的寄存器。所以干脆搞一个软件模拟gpio的通用代码,移植起来也方便,使用灵活

具体代码如下:


  1. #include <linux/module.h>
  2. #include <linux/config.h>
  3. #include <linux/errno.h>
  4. #include <linux/miscdevice.h>
  5. #include <linux/fcntl.h>
  6. #include <linux/init.h>
  7. #include <linux/delay.h>
  8. #include <linux/version.h>
  9. #include <linux/kernel.h>   
  10. #include <linux/fs.h>      
  11. #include <linux/types.h>   
  12. #include <linux/proc_fs.h>
  13. #include <asm/uaccess.h>
  14. #include <asm/system.h>
  15. #include <asm/rt2880/rt_mmap.h>
  16. #include <asm/system.h>   

  17. #include <asm/io.h>

  18. #include "gpio_i2c.h"
  19. #include "../ralink_gpio.h"


  20. #define DELAY(u)                udelay(u*100)

  21. #define RT2860REG(addr) (*(volatile u32 *)(addr))

  22. static void gpio_i2c_set_bit(int id, int onoff)
  23. {       
  24.         int tmp;

  25.         if(id<=21&&id>=0)
  26.         {
  27.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
  28.                 tmp |= (1<<(id));
  29.                 *(volatile u32 *)(RALINK_REG_PIODIR) = tmp;


  30.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
  31.                 tmp = (tmp&~(1<<(id)))|(onoff<<(id));
  32.                 *(volatile u32 *)(RALINK_REG_PIODATA) = tmp;
  33.         }
  34.         else if(id>=22&&id<=27)
  35.         {
  36.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO2722DIR));
  37.                 tmp |= (1<<(id-22));
  38.                 *(volatile u32 *)(RALINK_REG_PIO2722DIR) = tmp;


  39.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO2722DATA));
  40.                 tmp = (tmp&~(1<<(id-22)))|(onoff<<(id-22));
  41.                 *(volatile u32 *)(RALINK_REG_PIO2722DATA) = tmp;
  42.         }
  43.         else
  44.         {
  45.                 printk("####HU#### %s id %d invalid \r\n",__FUNCTION__,id);
  46.         }
  47. }

  48. static int gpio_i2c_get_bit(int id)
  49. {       
  50.         int tmp;

  51.         if(id<=21&&id>=0)
  52.         {
  53.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
  54.                 tmp &= ~(1<<(id));
  55.                 *(volatile u32 *)(RALINK_REG_PIODIR) = tmp;


  56.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
  57.                 return (tmp>>id&0x01);
  58.         }
  59.         else if(id>=22&&id<=27)
  60.         {
  61.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO2722DIR));
  62.                 tmp &= ~(1<<(id-22));
  63.                 *(volatile u32 *)(RALINK_REG_PIO2722DIR) = tmp;


  64.                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO2722DATA));
  65.                 return (tmp>>(id-22)&0x01);
  66.         }
  67.         else
  68.         {
  69.                 printk("####HU#### %s id %d invalid \r\n",__FUNCTION__,id);
  70.         }
  71. }

  72. static void i2c_clk(int onoff)
  73. {       
  74.         gpio_i2c_set_bit(2,onoff);
  75.        
  76. }

  77. static void i2c_dat(int onoff)
  78. {       
  79.         gpio_i2c_set_bit(1,onoff);
  80.        
  81. }




  82. static unsigned char i2c_data_read(void)
  83. {
  84. //        unsigned char tmp;
  85.        
  86. //        tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
  87. //        tmp &= ~(1<<(1));
  88. //        *(volatile u32 *)(RALINK_REG_PIODIR) = tmp;
  89. //               
  90. //        //DELAY(1);
  91. //               
  92. //        tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
  93. //        if((tmp&(1<<1)) != 0)
  94. //                return 1;
  95. //        else
  96. //                return 0;

  97.         return gpio_i2c_get_bit(1);
  98. }



  99. /*
  100. * sends a start bit via I2C rountine.
  101. *
  102. */
  103. static void i2c_start_bit(void)
  104. {
  105.         DELAY(1);
  106.         i2c_clk(1);
  107.                 i2c_dat(1);
  108.         DELAY(1);
  109.         i2c_dat(0);
  110.         DELAY(1);
  111. }

  112. /*
  113. * sends a stop bit via I2C rountine.
  114. *
  115. */
  116. static void i2c_stop_bit(void)
  117. {
  118.       
  119.                 i2c_clk(0);
  120.         i2c_dat(1);
  121.         DELAY(1);
  122.                 i2c_clk(1);
  123. }

  124. /*
  125. * sends a character over I2C rountine.
  126. *
  127. * @param  c: character to send
  128. *
  129. */
  130. static void i2c_send_byte(unsigned char c)
  131. {
  132.     int i;
  133.     local_irq_disable();
  134.         //i2c_clk(1);
  135.     for (i=0; i<8; i++)
  136.     {
  137.         i2c_clk(0);
  138.                 if (c & (1<<(7-i)))
  139.             i2c_dat(1);
  140.         else
  141.             i2c_dat(0);
  142.                
  143.         DELAY(1);
  144.                
  145.                 i2c_clk(1);
  146.                 DELAY(1);
  147.     }
  148.    // i2c_dat(1);
  149.     local_irq_enable();
  150. }

  151. /*  receives a character from I2C rountine.
  152. *
  153. *  [url=home.php?mod=space&uid=1141835]@Return[/url] value: character received
  154. *
  155. */
  156. static unsigned char i2c_receive_byte(void)
  157. {
  158.     int j=0;
  159.     int i;
  160.     unsigned char regvalue;

  161.     local_irq_disable();

  162.         i2c_data_read();
  163.     for (i=0; i<8; i++)
  164.     {
  165.         i2c_clk(0);
  166.                 DELAY(1);

  167.                 i2c_clk(1);
  168.                
  169.                 i2c_data_read();
  170.         if (i2c_data_read())
  171.             j+=(1<<(7-i));
  172.                
  173.         DELAY(1);
  174.                
  175.                
  176.     }
  177.     local_irq_enable();
  178.    // i2c_dat(0);
  179.    // DELAY(1);

  180.     return j;
  181. }

  182. /*  receives an acknowledge from I2C rountine.
  183. *
  184. *  @return value: 0--Ack received; 1--Nack received
  185. *         
  186. */
  187. static int i2c_receive_ack(void)
  188. {
  189.     int nack;
  190.    
  191.     i2c_data_read();
  192.     i2c_clk(0);
  193.     DELAY(1);
  194.         i2c_clk(1);
  195.        
  196.         i2c_data_read();
  197.         nack = i2c_data_read();
  198.     DELAY(1);

  199.         i2c_dat(1);

  200.     if (nack == 0)
  201.         return 1;

  202.     return 0;
  203. }

  204. /*
  205. * sends an acknowledge over I2C rountine.
  206. *
  207. */
  208. static void i2c_send_ack(void)
  209. {
  210.     i2c_clk(0);
  211.         i2c_dat(0);
  212.     DELAY(1);
  213.        
  214.     i2c_clk(1);
  215.         DELAY(1);
  216.        
  217. }

  218. static void si2c_init()
  219. {
  220.         RT2860REG(RALINK_REG_GPIOMODE)=RT2860REG(RALINK_REG_GPIOMODE)|(1<<0);
  221. }

  222. static void si2c_exit()
  223. {
  224.        
  225. }



  226. /*  
  227. *  read data from the I2C bus by GPIO simulated of a device rountine.
  228. *
  229. *  @param  devaddress:  address of the device
  230. *  @param  address: address of register within device
  231. *   
  232. *  @return value: data from the device readed
  233. *
  234. */
  235. unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
  236. {
  237.     int rxdata;

  238.         si2c_init();
  239.        
  240.     i2c_start_bit();
  241.     i2c_send_byte((unsigned char)((devaddress<<1)|0));
  242.     i2c_receive_ack();
  243.     i2c_send_byte(address);
  244.     i2c_receive_ack();   
  245.     i2c_start_bit();
  246.     i2c_send_byte((unsigned char)((devaddress<<1)|1));
  247.     i2c_receive_ack();
  248.     rxdata = i2c_receive_byte();
  249.     i2c_send_ack();
  250.     i2c_stop_bit();
  251.        
  252.         si2c_exit();
  253.     return rxdata;
  254. }
  255. EXPORT_SYMBOL(gpio_i2c_read);


  256. /*
  257. *  writes data to a device on the I2C bus rountine.
  258. *
  259. *  @param  devaddress:  address of the device
  260. *  @param  address: address of register within device
  261. *  @param  data:   data for write to device
  262. *
  263. */

  264. void gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char data)
  265. {
  266.         si2c_init();
  267.        
  268.     i2c_start_bit();
  269.     i2c_send_byte((unsigned char)((devaddress<<1)|0));
  270.     i2c_receive_ack();
  271.     i2c_send_byte(address);
  272.     i2c_receive_ack();
  273.     i2c_send_byte(data);
  274.            i2c_receive_ack();
  275.     i2c_stop_bit();

  276.            si2c_exit();
  277. }
  278. EXPORT_SYMBOL(gpio_i2c_write);










  279. /*
  280. * initializes I2C interface routine.
  281. *
  282. * @return value:0--success; 1--error.
  283. *
  284. */
  285. static int __init gpio_i2c_init(void)
  286. {

  287. }

  288. static void __exit gpio_i2c_exit(void)
  289. {
  290.        
  291. }

  292. module_init(gpio_i2c_init);
  293. module_exit(gpio_i2c_exit);

  294. #ifdef MODULE
  295. #include <linux/compile.h>
  296. #endif
  297. MODULE_INFO(build, UTS_VERSION);
  298. MODULE_LICENSE("GPL");
  299. MODULE_VERSION("HI_VERSION=" OSDRV_MODULE_VERSION_STRING);

复制代码


gpio_i2c_set_bit与gpio_i2c_get_bit设置gpio高低的,DELAY宏为延时方法,理论只要实现这几个值就能够实现标准的gpio_i2c的功能了


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top