gpio模擬i2c驅動

該程序可以作爲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\n");
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\n");
542 }
543
544
545
546 module_init(gpio_ctrl_drv_module_init);
547 module_exit(gpio_ctrl_drv_module_exit);
548 MODULE_LICENSE("GPL");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章