K210开发板(五)—拍摄和KEYPAD照片查看
Created At : 2023-09-19 00:16
Count:1.5k
Views 👀 :
简介: 本篇博客用于记录K210的学习和自己遇到的问题,主要内容为实现拍摄和照片查看功能,摄像头实时将画面传到LCD上,按下BOOT拍照记录当前照片,按下KEYPAD进入照片查看,左滚KEYPAD查看上一张照片,右滚KEYPAD查看下一张照片,再次按下KEYPAD退出照片查看,重新恢复摄像功能。由于参考资料的教程比较齐全,本文会着重于讲述自己遇到的问题和解决方案
参考资料:http://www.yahboom.com/study/K210-Developer-Kit 提取码:moj1
一.实验准备 1.函数介绍 1.1 lcd_draw_picture 设置GPIO中断触发模式
参数成员
描述
输入输出
x
起始坐标
输入
y
起始坐标
输入
width
图像宽度
输入
height
图像长度
输入
*ptr
图像数据存放地址
输入
二.实验步骤 1.配置 过多了,这里就不贴了,见参考资料摄像头显示实验、按键中断实验、keypad控制RGB灯实验
2.初始化 见参考文件就行,注意引脚定义不要冲突了
3.主体 3.1 中断回调函数 3.1.1 boot中断函数 下降沿触发,每次按下boot时触发中断,申请一片320*240的空间,存放照片数据,最后保存地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int key_irq_cb (void * ctx) { phoNum++; uint32_t *tmp = (uint32_t *)(ctx); (*tmp)++; if (*tmp<5 ){ uint32_t * keyptr=keyptrs[phoNum-1 ]; keyptr=(uint32_t *)iomem_malloc(CAM_WIDTH_PIXEL * CAM_HIGHT_PIXEL * 2 ); uint32_t *display_buf=display_buf_addr; for (int i=0 ;i<76800 ;i++){ *(keyptr+i)=*(display_buf+i); } uint32_t keyptr_addr=keyptr; keyptr_addrs[phoNum-1 ]=keyptr_addr; lcd_draw_picture(0 , 0 , 320 , 240 ,keyptr_addr); sleep(1 ); }else { printf ("Photo space is full\n" ); } return 0 ; }
3.1.1 boot中断函数 下降沿触发,每次按下boot时触发中断,申请一片320*240的空间,存放照片数据,最后保存地址 //keypad中断函数
3.1.2 keypad中断函数 分为左滚动中断、右滚动中断、中键中断
3.1.2.1 左滚动中断 用互斥锁防止由于抖动而导致相同中断同时发生好几起,当向左滚动时keypad_idx
减一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int keypad_left_icf (void * ctx) { msleep(10 ); keypad_left_icf_flag++; if (keypad_left_icf_flag>1 ){ keypad_left_icf_flag--; return 0 ; } gpio_pin_value_t state_keypad_left = gpiohs_get_pin(KEYPAD_LEFT_GPIONUM); if (state_keypad_left!=0 ){ keypad_left_icf_flag=0 ; return 0 ; }; if (keypad_left_icf_flag>1 ){ keypad_left_icf_flag--; return 0 ; } uint32_t *tmp = (uint32_t *)(ctx); printf ("Enter keypad left interrupt%d\n" ,keypad_left_icf_flag); if (phoNum==0 ){ printf ("There are currently no photos available\n" ); }else if ((*tmp)==1 ){ printf ("This is currently the first photo, there are no more previous photos available\n" ); }else { (*tmp)--; } keypad_left_icf_flag=0 ; return 0 ; }
3.1.2.2 左滚动中断 用互斥锁防止由于抖动而导致相同中断同时发生好几起,当向左滚动时keypad_idx
加一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int keypad_right_icf (void * ctx) { msleep(10 ); keypad_right_icf_flag++; if (keypad_right_icf_flag>1 ){ keypad_right_icf_flag--; return 0 ; } gpio_pin_value_t state_keypad_right = gpiohs_get_pin(KEYPAD_RIGHT_GPIONUM); if (state_keypad_right!=0 ){ keypad_right_icf_flag=0 ; return 0 ; }; uint32_t *tmp = (uint32_t *)(ctx); printf ("Enter keypad right interrupt\n" ); if (phoNum==0 ){ printf ("There are currently no photos available\n" ); }else if ((*tmp)==phoNum){ printf ("This is currently the last photo, there are no further photos available\n" ); }else { (*tmp)++; } keypad_right_icf_flag=0 ; return 0 ; }
3.1.2.3 中键中断 中键按下时,如果是第一次按下,允许进入中断,如果此时有照片,就在while循环内查看当前第keypad_idx
张照片,左滚动右滚动优先级都大于中键,可以用于切换照片,boot按键优先级小于中键,需要等待再次按下中键,此时退出照片查看,可以重新使用拍照功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 int keypad_middle_icf (void * ctx) { msleep(10 ); keypad_middle_icf_flag++; if (keypad_middle_icf_flag>1 ){ keypad_middle_icf_flag--; return 0 ; } gpio_pin_value_t state_keypad_middle = gpiohs_get_pin(KEYPAD_MIDDLE_GPIONUM); if (state_keypad_middle!=0 ){ keypad_middle_icf_flag--; return 0 ; }; uint32_t *tmp = (uint32_t *)(ctx); if (phoNum==0 ){ printf ("There are currently no photos available\n" ); }else { printf ("enter photo view\n" ); while (gpiohs_get_pin(KEYPAD_MIDDLE_GPIONUM)!=1 ); while (gpiohs_get_pin(KEYPAD_MIDDLE_GPIONUM)==1 ){ lcd_draw_picture(0 , 0 , 320 , 240 , keyptr_addrs[keypad_idx-1 ]); } } while (gpiohs_get_pin(KEYPAD_MIDDLE_GPIONUM)!=1 ); keypad_middle_icf_flag--; printf ("exit keypad_enter_mid_icf%d %d\n" ,keypad_middle_icf_flag,keypad_middle_icf_exit_flag); return 0 ; }
3.1.3 摄像头中断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static int on_dvp_irq_cb (void *ctx) { if (dvp_get_interrupt(DVP_STS_FRAME_FINISH)) { dvp_set_display_addr((uint32_t )display_buf_addr); dvp_clear_interrupt(DVP_STS_FRAME_FINISH); g_dvp_finish_flag = 1 ; } else { if (g_dvp_finish_flag == 0 ) dvp_start_convert(); dvp_clear_interrupt(DVP_STS_FRAME_START); } return 0 ; }
3.2 while循环 1 2 3 4 while (g_dvp_finish_flag == 0 );g_dvp_finish_flag = 0 ; lcd_draw_picture(0 , 0 , 320 , 240 , display_buf_addr);
三.实验总结 遇到问题 :
KEYPAD相同中断函数同时触发两次,尽管用了互斥变量还是没能解决
LCD显示已经拍摄的照片时(除最后一张),显示花纹图像,未正确显示
LCD显示偶尔会黑屏、失真
终端中文乱码,打印出问题
KEYPAD中键检测不灵敏,需要按一小段时间才能检测到
解决方案 :
未解决
未解决,估计和内存存放地址有关
Reset可解决,但原因未找明,仍会复发
改用英文,每行加回车
未解决
Tips :引脚过多,注意软件引脚定义,不要冲突
结语: 第一次功能比较多的复合实验,遇到的冲突不少,需要注意不同功能间的交互、变量统一、冲突问题
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 21009200039@stu.xidian.edu.cn