K210开发板(五)—拍摄和KEYPAD照片查看


简介:
  本篇博客用于记录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
//button中断函数
/*
uint32_t phoNum=0;
uint32_t g_count=-1;
uint32_t *keyptrs[5]={NULL,NULL,NULL,NULL,NULL};
uint32_t keyptr_addrs[5]={};
*/
int key_irq_cb(void* ctx){
phoNum++; //照片数量
uint32_t *tmp = (uint32_t *)(ctx); //button使用次数
(*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中断函数

  分为左滚动中断、右滚动中断、中键中断

1
2
3
4
5
6
7
/*
uint32_t keypad_idx=1; //当前照片索引
//是否处于中断标志
uint32_t keypad_left_icf_flag=0;
uint32_t keypad_middle_icf_flag=0;
uint32_t keypad_right_icf_flag=0;
*/

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)
{
//读取DVP中断状态,如果完成则刷新显示地址的数据,并清除中断标志,否则读取摄像头数据
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);

三.实验总结

遇到问题

  1. KEYPAD相同中断函数同时触发两次,尽管用了互斥变量还是没能解决
  2. LCD显示已经拍摄的照片时(除最后一张),显示花纹图像,未正确显示
  3. LCD显示偶尔会黑屏、失真
  4. 终端中文乱码,打印出问题
  5. KEYPAD中键检测不灵敏,需要按一小段时间才能检测到

解决方案

  1. 未解决
  2. 未解决,估计和内存存放地址有关
  3. Reset可解决,但原因未找明,仍会复发
  4. 改用英文,每行加回车
  5. 未解决

Tips:引脚过多,注意软件引脚定义,不要冲突


结语:
  第一次功能比较多的复合实验,遇到的冲突不少,需要注意不同功能间的交互、变量统一、冲突问题



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 21009200039@stu.xidian.edu.cn

💰

×

Help us with donation