zoukankan      html  css  js  c++  java
  • Examples

    前段时间做项目,需要gpio模拟i2c通信,最后参考了一些资料,然后编写了一个程序。现在发出来,以免以后忘记,也为一些需要的朋友提供参考。不喜勿喷哈。

    /* 说明:该程序是基于atmel公司的sama5d35 MCU 用其中两个GPIO引脚模拟i2c通信。
    * 其中两个引脚连接到了hd1650上面。然后检测按键扫描的驱动
    * */

    该程序可以作为gpio模拟i2c程序的参考。不同的平台,函数实现不同,但是i2c通信的时序和原理是相同的。希望对一些朋友有帮助。

      1 #include<linux/init.h>
      2 #include<linux/module.h>
      3 #include<linux/kernel.h>
      4 #include<linux/sched.h>
      5 #include<linux/init.h>
      6 #include<linux/sched.h>
      7 #include<linux/completion.h>
      8 #include <asm/system.h>
      9 #include <linux/param.h>
     10 #include<linux/gpio.h>
     11 #include<linux/cdev.h>
     12 #include<linux/fs.h>
     13 #include<linux/device.h>
     14 #include<linux/slab.h>
     15 #include<asm/uaccess.h>
     16 #include<linux/delay.h>
     17 #include<linux/miscdevice.h>
     18 
     19 
     20 
     21 
     22 /* 定义GPIO引脚值,这个在内核里面有定义 */
     23 #define GPIO_PC30 94
     24 #define GPIO_PC31 95
     25 
     26 
     27 /* 定义GPIO引脚结构体,用于和上层进行通信 */
     28 typedef struct gpio_ctrl_blk{
     29     int pin;
     30     int value;
     31 }gpio_cblk_t;
     32 
     33 
     34 #define HD1650_DEV_ID 'k'
     35 #define GET_KEY             _IOWR (HD1650_DEV_ID,0x34,int)
     36 
     37 
     38 /* 定义延时函数,用于i2c通信 */
     39 #define DELAY_BUILD()    udelay(10)
     40 #define DELAY()            udelay(10)
     41 
     42 /* this define copy from datasheet */
     43 #define CMD_SYSOFF    0x4800
     44 #define CMD_SYSON    0x4801
     45 #define CMD_SLEEPOFF    0x4800
     46 #define CMD_SLEEPON    0x4804
     47 #define CMD_7SEGON    0x4809
     48 #define CMD_8SEGON    0x4801
     49 
     50 #define CMD_7SEGON1    0x4819
     51 #define CMD_7SEGON2    0x4829
     52 #define CMD_7SEGON3    0x4839
     53 #define CMD_7SEGON4    0x4849
     54 #define CMD_7SEGON5    0x4859
     55 #define CMD_7SEGON6    0x4869
     56 #define CMD_7SEGON7    0x4879
     57 #define CMD_7SEGON8    0x4809
     58 
     59 #define CMD_8SEGON1    0x4811
     60 #define CMD_8SEGON2    0x4821
     61 #define CMD_8SEGON3    0x4831
     62 #define CMD_8SEGON4    0x4841
     63 #define CMD_8SEGON5    0x4851
     64 #define CMD_8SEGON6    0x4861
     65 #define CMD_8SEGON7    0x4871
     66 #define CMD_8SEGON8    0x4801
     67 
     68 #define CMD_DIG0(x)    0x6800 | (x)
     69 #define CMD_DIG1(x)    0x6A00 | (x)
     70 #define CMD_DIG2(x)    0x6C00 | (x)
     71 #define CMD_DIG3(x)    0x6E00 | (x)
     72 #define CMD_GETKEY    0x4F00
     73 
     74 /*show define*/
     75 /******************************************************************
     76   a
     77   __
     78 f|__|b
     79 e|__|c .dop  中间那段为g
     80 d
     81 *******************************************************************/
     82 
     83 //数码管末一段的值
     84 #define BA        0x1
     85 #define BB        0x1<<1
     86 #define BC        0x1<<2
     87 #define BD        0x1<<3
     88 #define BE        0x1<<4
     89 #define BF        0x1<<5
     90 #define BG        0x1<<6
     91 #define BP        0x1<<7
     92 
     93 //数码管显示的字符的值
     94 #define TM_A        BF | BA | BB | BG | BE | BC
     95 #define TM_B        BF | BE | BG | BD | BC
     96 #define TM_C        BG | BE | BD
     97 #define TM_D        BB | BC | BD | BE | BG
     98 #define TM_E        BA | BF | BG | BE | BD
     99 #define TM_G        BA | BF | BE | BD | BC
    100 #define TM_F        BA | BF | BG | BE
    101 #define TM_H        BF | BE | BG | BC
    102 #define TM_I        BB | BC
    103 #define TM_J        BB | BC | BD | BE
    104 #define TM_K        BF | BG | BE | BC | BB
    105 #define TM_L        BF | BE | BD
    106 #define TM_M        0
    107 #define TM_N        BE | BG | BC
    108 #define TM_O        BG | BC | BD | BE
    109 #define TM_P        BA | BB |BG | BF |BE
    110 #define TM_Q        BF | BA | BB | BG | BC
    111 #define TM_R        BE | BG
    112 #define TM_S        BA | BF | BG | BC | BD
    113 #define TM_T        BF | BG | BE | BD
    114 #define TM_U        BF | BE | BD | BC | BB
    115 #define TM_V        BE | BD | BC
    116 #define TM_W        0
    117 #define TM_X        0
    118 #define TM_Y        0
    119 #define TM_Z        0
    120 
    121 #define TM_0        BA | BB | BC | BD | BE | BF
    122 #define TM_1        BB | BC
    123 #define TM_2        BA | BB | BG | BE | BD
    124 #define TM_3        BA | BB | BC | BD | BG
    125 #define TM_4        BF | BG | BB | BC
    126 #define TM_5        BA | BF | BG | BC | BD
    127 #define TM_6        BA | BF | BG | BE | BD | BC
    128 #define TM_7        BF | BA | BB | BC
    129 #define TM_8        BA | BB | BC | BD | BE | BF | BG
    130 #define TM_9        BA | BB | BC | BD | BG | BF
    131 
    132 unsigned char TM_NUM[] = {TM_0, TM_1, TM_2, TM_3, TM_4,
    133 TM_5, TM_6, TM_7, TM_8, TM_9}; //定义键值
    134 
    135 unsigned char TM_CHAR[] = {TM_A, TM_B, TM_C, TM_D, TM_E, TM_F, TM_G,
    136 TM_H, TM_I, TM_J, TM_K, TM_L, TM_M, TM_N, 
    137 TM_O, TM_P, TM_Q, TM_R, TM_S, TM_T, TM_U, 
    138 TM_V, TM_W, TM_X, TM_Y, TM_Z};
    139 
    140 
    141 /*对i2c操作函数*/
    142 static void i2c_start(void);
    143 static void i2c_stop(void);
    144 static void i2c_send(unsigned char data);
    145 static unsigned char i2c_recv(unsigned char *data);
    146 static int i2c_get_ack(void);
    147 static int i2c_get_ack_getkey(void);
    148 
    149 
    150 static void CLK_OUT(void); 
    151 static void SDA_IN(void);
    152 static void SDA_OUT(void);
    153 static int GET_SDA(void);
    154 static void CLK_H(void);
    155 static void CLK_L(void);
    156 static void SDA_H(void);
    157 static void SDA_L(void);
    158 
    159 static unsigned char hd1650_sendcmd(unsigned short cmd);
    160 
    161 
    162 /*************函数实现******************/
    163 
    164 
    165 /* 设置时钟引脚为输出引脚 */
    166 static void CLK_OUT(void) 
    167 {
    168     gpio_cblk_t gpio_dev;
    169     gpio_dev.pin = GPIO_PC31;
    170     gpio_dev.value = 1;
    171 
    172     at91_set_gpio_output(gpio_dev.pin,gpio_dev.value); 
    173 }
    174 
    175 /* 设置数据引脚为输出引脚 */
    176 static void SDA_OUT(void)
    177 {
    178     gpio_cblk_t gpio_dev;
    179 
    180     gpio_dev.pin = GPIO_PC30;
    181     gpio_dev.value = 1;
    182     
    183     at91_set_gpio_output(gpio_dev.pin,gpio_dev.value);
    184 }
    185 
    186 /* 设置数据引脚为输入引脚 */
    187 static void SDA_IN(void)
    188 {
    189     gpio_cblk_t gpio_dev;
    190 
    191     gpio_dev.pin = GPIO_PC30;
    192     gpio_dev.value = 1;
    193 
    194     at91_set_gpio_input(gpio_dev.pin,gpio_dev.value);
    195 }
    196 
    197 /* 取数据引脚的值 */
    198 static int GET_SDA(void)
    199 {
    200     gpio_cblk_t gpio_dev;
    201 
    202     gpio_dev.pin = GPIO_PC30;
    203     gpio_dev.value = at91_get_gpio_value(gpio_dev.pin);
    204 
    205     return gpio_dev.value;
    206 }
    207 
    208 /* 设置时钟引脚为高 */
    209 static void CLK_H(void)
    210 {
    211     gpio_cblk_t gpio_dev;
    212     gpio_dev.pin = GPIO_PC31;
    213     gpio_dev.value = 1;
    214 
    215     at91_set_gpio_value(gpio_dev.pin,gpio_dev.value);
    216 }
    217 
    218 /* 设置时钟引脚为低*/
    219 static void CLK_L(void)
    220 {
    221     gpio_cblk_t gpio_dev;
    222     gpio_dev.pin = GPIO_PC31;
    223     gpio_dev.value = 0;
    224 
    225     at91_set_gpio_value(gpio_dev.pin,gpio_dev.value);
    226 }
    227 
    228 /* 设置数据引脚为高 */
    229 static void SDA_H(void)
    230 {
    231     gpio_cblk_t gpio_dev;
    232     gpio_dev.pin = GPIO_PC30;
    233     gpio_dev.value = 1;
    234 
    235     at91_set_gpio_value(gpio_dev.pin,gpio_dev.value);
    236 }
    237 
    238 /* 设置数据引脚为低 */
    239 static void SDA_L(void)
    240 {
    241     gpio_cblk_t gpio_dev;
    242     gpio_dev.pin = GPIO_PC30;
    243     gpio_dev.value = 0;
    244 
    245     at91_set_gpio_value(gpio_dev.pin,gpio_dev.value);
    246 }
    247 
    248 
    249 
    250 
    251 /*****************************global function *********************************/
    252 void hd1650_init(void)
    253 {
    254     hd1650_sendcmd(CMD_8SEGON);
    255 
    256     /* clear 4 segment */
    257     hd1650_sendcmd(CMD_DIG0(0x00));
    258     hd1650_sendcmd(CMD_DIG1(0x00));
    259     hd1650_sendcmd(CMD_DIG2(0x00));
    260     hd1650_sendcmd(CMD_DIG3(0x00));
    261 }
    262 
    263 unsigned char asc2code(unsigned char src)
    264 {
    265     
    266     if(src <= 9)
    267         return TM_NUM[src];
    268     else if(src >= '0' && src <= '9')
    269         return TM_NUM[src - '0'];
    270     else if(src >= 'a' && src <= 'z')
    271         return TM_CHAR[src - 'a'];
    272     else if(src >= 'A' && src <= 'Z')
    273         return TM_CHAR[src - 'A'];
    274     else
    275         return 0;
    276     
    277 }
    278 
    279 /*data : 0-6
    280  * pos: 2
    281  * dot_flag:数码管的点的亮灭*/
    282 void hd1650_show_each(unsigned char data, unsigned char pos,unsigned char dot_flag)
    283 {
    284     unsigned char tmpData;
    285     //tmpData = asc2code(data);
    286     switch(pos)
    287     {
    288         case 1:
    289             hd1650_sendcmd(CMD_DIG0(tmpData));
    290             break;
    291         case 2:
    292             if(dot_flag)
    293                 hd1650_sendcmd(CMD_DIG1(tmpData|0x80));
    294             else
    295                 //hd1650_sendcmd(CMD_DIG1(tmpData&0x7f));
    296                 hd1650_sendcmd(CMD_DIG1(data));
    297             break;
    298         case 3:
    299             hd1650_sendcmd(CMD_DIG2(tmpData));
    300             break;
    301         case 4:
    302             hd1650_sendcmd(CMD_DIG3(tmpData));
    303             break;
    304     }
    305 }
    306 
    307 
    308 
    309 unsigned char hd1650_getkey(unsigned char *key)
    310 {
    311     unsigned char tmp = 0;
    312 
    313     
    314     tmp = hd1650_sendcmd( CMD_GETKEY );
    315 
    316     if((tmp & 0x40)== 0)
    317         tmp = 0x2e;
    318 
    319     if( key )
    320         *key = tmp;
    321 
    322     return tmp;
    323 }
    324 
    325 
    326 
    327 /*****************************local function implemention*********************************/
    328 /*****************************DO NOT MODIFY*********************************/
    329 static void i2c_start(void)
    330 {
    331     CLK_OUT();
    332     SDA_OUT();
    333 
    334     SDA_H();
    335     DELAY();
    336     CLK_H();
    337     DELAY_BUILD();
    338     SDA_L();
    339     DELAY();
    340 }
    341 
    342 static void i2c_stop(void)
    343 {
    344     SDA_OUT();
    345     SDA_L();
    346     DELAY();
    347 
    348     CLK_H();
    349     DELAY_BUILD();
    350     SDA_H();
    351     DELAY();
    352 
    353 
    354 }
    355 
    356 /* MSB */
    357 static void i2c_send(unsigned char data)
    358 {
    359     unsigned char i = 0;
    360     for(; i < 8 ; i++)
    361     {
    362         CLK_L();
    363         DELAY_BUILD();
    364         if( data & 0x80 )
    365             SDA_H();
    366         else
    367             SDA_L();
    368         data <<= 1;
    369         DELAY();
    370         CLK_H();
    371         DELAY();
    372     }
    373 }
    374 
    375 static unsigned char i2c_recv(unsigned char *data)
    376 {
    377     unsigned char i = 0, tmp=0;
    378     SDA_IN();
    379     for(; i < 8 ; i++)
    380     {
    381         CLK_L();
    382         DELAY();
    383         CLK_H();
    384         DELAY_BUILD();
    385         tmp <<= 1;
    386         tmp |= GET_SDA();
    387         
    388         DELAY();
    389     }
    390     SDA_OUT();
    391 
    392     if( data )
    393         *data = tmp;
    394     return tmp;
    395 }
    396 
    397 static int i2c_get_ack(void)
    398 {
    399     int i = 30;
    400 
    401     CLK_L();
    402     SDA_IN();
    403     DELAY_BUILD();
    404     
    405     CLK_H();
    406     DELAY();
    407     while(GET_SDA() && i-- );
    408     CLK_L();
    409     SDA_OUT();
    410 
    411     return 1;/*!!!Fixme. this should return the right value, but sometimes the ack cannot get */
    412 }
    413 
    414 static int i2c_get_ack_getkey(void)
    415 {
    416     int i = 30;
    417 
    418     CLK_L();
    419     SDA_IN();
    420     DELAY_BUILD();
    421     
    422     CLK_H();
    423     DELAY();
    424     while(!GET_SDA() && i-- );
    425     CLK_L();
    426     SDA_OUT();
    427 
    428     return 1;/*!!!Fixme. this should return the right value, but sometimes the ack cannot get */
    429 }
    430 
    431 
    432 static unsigned char hd1650_sendcmd(unsigned short cmd)
    433 {
    434     unsigned char tmp_data = cmd>>8;
    435 
    436     i2c_start();
    437     i2c_send(tmp_data);
    438     if(1 != i2c_get_ack() )
    439     {
    440         /* printk some error
    441         * hd1650 didnot send the ack
    442         */
    443     }
    444 
    445     if( cmd == CMD_GETKEY )
    446     {
    447         i2c_recv(&tmp_data);
    448         if(1 != i2c_get_ack_getkey())
    449         {
    450             /* printk some error
    451             * hd1650 didnot send the ack
    452             */
    453         }
    454     }else{
    455         tmp_data = cmd&0x0ff;
    456         i2c_send(tmp_data);
    457         if(1 != i2c_get_ack())
    458         {
    459             /* printk some error
    460             * hd1650 didnot send the ack
    461             */
    462         }
    463     }
    464 
    465     
    466     i2c_stop();
    467 
    468     return tmp_data;/* just valid for the CMD_GETKEY */
    469 }
    470 
    471 
    472 
    473 
    474 /*******END OF THE FILE *********/
    475 
    476 static int hd1650_ctrl_drv_open(struct node *node, struct file *file )
    477 {
    478     return 0;
    479 }
    480 
    481 static int hd1650_ctrl_drv_release(struct node *node, struct file *file )
    482 {
    483     return 0;
    484 }
    485 
    486 static long hd1650_ctrl_drv_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    487 {
    488     unsigned char key = 0;
    489 
    490     int ret = 0;
    491     
    492     switch (cmd) {
    493     case GET_KEY:
    494             hd1650_getkey(&key);
    495             ret = put_user(key,(int *)arg);
    496             break;
    497     default:
    498         return -EINVAL;
    499 
    500     }
    501 
    502     
    503     
    504     return 0;
    505 }
    506 
    507 static struct file_operations hd1650_ctl_drv_fileops = {
    508     .owner = THIS_MODULE,
    509     .open = hd1650_ctrl_drv_open,
    510     .unlocked_ioctl = hd1650_ctrl_drv_unlocked_ioctl,
    511     .release = hd1650_ctrl_drv_release
    512 };
    513 
    514 static struct miscdevice hd1650_dev = {
    515     MISC_DYNAMIC_MINOR,
    516     "hd1650_dev",
    517     &hd1650_ctl_drv_fileops,
    518 };
    519 int gpio_ctrl_drv_module_init(void)
    520 {
    521     int ret = 0;
    522 
    523 
    524     ret = misc_register(&hd1650_dev);
    525     if(ret != 0)
    526     {
    527         ret = -EFAULT;
    528         return ret;
    529     }
    530     hd1650_init();
    531     hd1650_show_each(0x40 ,2,0);
    532     printk("hd1650_drv_init ok
    ");
    533     return 0;
    534 }
    535 
    536 
    537 void gpio_ctrl_drv_module_exit(void)
    538 {
    539 
    540     misc_deregister(&hd1650_dev);
    541     printk("gpio_drv_exit ok
    ");
    542 }
    543 
    544 
    545 
    546 module_init(gpio_ctrl_drv_module_init);
    547 module_exit(gpio_ctrl_drv_module_exit);
    548 MODULE_LICENSE("GPL");
  • 相关阅读:
    JMeter 压测基础(四)——Java工程测试
    Docker 实战(二)——centos7镜像安装nginx,将安装nginx的centos容器生成新的镜像,并导出
    JMeter压测基础(三)——Mysql数据库
    Jmeter压测基础(二)——Badboy功能、Jmeter参数化、检查点、集合点、动态关联、图形监控
    API 自动化框架
    Python Flask Restful
    【19】Grafana添加Zabbix为数据源
    【18】使用公共邮箱发送邮件
    xls格式转化为txt格式
    【17】自动发现磁盘脚本
  • 原文地址:https://www.cnblogs.com/hjj801006/p/4864602.html
Copyright © 2011-2022 走看看