前段时间做项目,需要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\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");
时间: 2024-10-07 06:33:09