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");
原文地址:https://www.cnblogs.com/hjj801006/p/4864602.html