利用STM32控制ov2640軟件二值化采集數據,進行圖像識別,可以操作機械臂
本實驗將實現如下功能:開機后,初始化攝像頭模塊(OV2640),如果初始化成功,則提示選擇模式:RGB565模式,或者JPEG模式。KEY0用于選擇RGB565模式,KEY1用于選擇JPEG模式。
當使用RGB565時,輸出圖像(固定為:UXGA)將經過縮放處理(完全由OV2640的DSP控制),顯示在LCD上面。我們可以通過KEY_UP按鍵選擇:1:1顯示,即不縮放,圖片不變形,但是顯示區域。ㄒ壕Х直媛蚀笮。蛘呖s放顯示,即將1600*1200的圖像壓縮到液晶分辨率尺寸顯示,圖片變形,但是顯示了整個圖片內容。通過KE0Y按鍵,可以設置對比度;KEY1按鍵,可以設置飽和度;KEY2按鍵,可以設置特效。
當使用JPEG模式時,圖像可以設置任意尺寸(QQVGA~UXGA),采集到的JPEG數據將先存放到STM32F4的內存里面,每當采集到一幀數據,就會關閉DMA傳輸,然后將采集到的數據發送到串口2(此時可以通過上位機軟件(串口攝像頭.exe)接收,并顯示圖片),之后再重新啟動DMA傳輸。我們可以通過KEY_UP設置輸出圖片的尺寸(QQVGA~UXGA)。通過KEY0按鍵,可以設置對比度;KEY1按鍵,可以設置飽和度;KEY2按鍵,可以設置特效。
注意:本實驗需要有ALIENTEK OV2640攝像頭模塊才可以做。
單片機源程序如下:
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "led.h"
- #include "key.h"
- #include "fing.h"
- #include "lcd.h"
- #include "usmart.h"
- #include "usart2.h"
- #include "timer.h"
- #include "ov2640.h"
- #include "dcmi.h"
- u8 ov2640_mode=0; //工作模式:0,RGB565模式;1,JPEG模式
- u8 x=174,wide=51,mode=0,stop=1;
- u8 tempdrum[4][201];
- u8 delaytime=50,time=0;
- #define jpeg_buf_size 31*1024 //定義JPEG數據緩存jpeg_buf的大小(*4字節)
- __align(4) u32 jpeg_buf[jpeg_buf_size]; //JPEG數據緩存buf
- volatile u32 jpeg_data_len=0; //buf中的JPEG有效數據長度
- volatile u8 jpeg_data_ok=0; //JPEG數據采集完成標志
- //0,數據沒有采集完;
- //1,數據采集完了,但是還沒處理;
- //2,數據已經處理完成了,可以開始下一幀接收
- void jpeg_data_process(void)
- {
- if(ov2640_mode)//只有在JPEG格式下,才需要做處理.
- {
- if(jpeg_data_ok==0) //jpeg數據還未采集完?
- {
- DMA_Cmd(DMA2_Stream1, DISABLE);//停止當前傳輸
- while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置
- jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);//得到此次數據傳輸的長度
-
- jpeg_data_ok=1; //標記JPEG數據采集完按成,等待其他函數處理
- }
- if(jpeg_data_ok==2) //上一次的jpeg數據已經被處理了
- {
- DMA2_Stream1->NDTR=jpeg_buf_size;
- DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//傳輸長度為jpeg_buf_size*4字節
- DMA_Cmd(DMA2_Stream1, ENABLE); //重新傳輸
- jpeg_data_ok=0; //標記數據未采集
- }
- }
- }
- void KeyMode()
- {
- u8 msgbuf2[20];
- DCMI_Stop(); //停止顯示
-
-
- if(WK_UP==1)
- {
- mode+=1;
- if(mode==3)
- {
- mode=0;
- sprintf((char*)msgbuf2,"x=%d w=%d",x,wide);//g
- LCD_ShowString(200,200,100,16,16,msgbuf2);//顯示提示內容
- }
- sprintf((char*)msgbuf2,"mode=%d",mode);//g
- LCD_ShowString(200,220,100,16,16,msgbuf2);//顯示提示內容
- while(WK_UP==1);
- }
-
-
-
- if(mode==1)
- {
-
- if(KEY0==0)
- {
- x+=1;
- sprintf((char*)msgbuf2," x=%d ",x);//g
- LCD_ShowString(200,200,100,16,16,msgbuf2);//顯示提示內容
- while(KEY0==0);
- }
- if(KEY2==0)
- {
- x-=1;
- sprintf((char*)msgbuf2," x=%d ",x);//g
- LCD_ShowString(200,200,100,16,16,msgbuf2);//顯示提示內容
- while(KEY2==0);
- }
- }
- if(mode==2)
- {
- if(KEY0==0)
- {
- wide+=1;
- sprintf((char*)msgbuf2," w=%d ",wide);//g
- LCD_ShowString(200,200,100,16,16,msgbuf2);//顯示提示內容
- while(KEY0==0);
- }
- if(KEY2==0)
- {
- wide-=1;
- sprintf((char*)msgbuf2," w=%d ",wide);//g
- LCD_ShowString(200,200,100,16,16,msgbuf2);//顯示提示內容
- while(KEY0==0);
- }
- }
- if(mode==0)
- {
- if(KEY0==0)
- {
- delaytime+=1;
- sprintf((char*)msgbuf2," w=%d ",delaytime);//g
- LCD_ShowString(200,220,100,16,16,msgbuf2);//顯示提示內容
- while(KEY0==0);
- }
- if(KEY2==0)
- {
- delaytime-=1;
- sprintf((char*)msgbuf2," w=%d ",delaytime);//g
- LCD_ShowString(200,220,100,16,16,msgbuf2);//顯示提示內容
- while(KEY0==0);
- }
- }
- DCMI_Start();
- }
- void getcolor(tx,ty,num)
- {
- u8 msgbuf1[15]; //消息緩存區
- u16 tempcolor;
-
-
- DCMI_Stop(); //停止顯示
- tempcolor=LCD_ReadPoint(tx,ty);
-
- sprintf((char*)msgbuf1,"%d",(int) ((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5));//g
- LCD_ShowString(tx-8,ty+24,210,16,16,msgbuf1);//顯示提示內容
-
- if((int) ((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5)>30) //軟件二值化
- {
- LCD_Fill((num-1)*120+1,150-20,num*120-1,150+20,WHITE);
- tempdrum[num-1][time]=1;
- }
- else
- {
- LCD_Fill((num-1)*120+1,150-20,num*120-1,150+20,BLACK);
- tempdrum[num-1][time]=0;
- }
-
-
- LCD_DrawRectangle(tx-1,ty-1, tx+1, ty+1);
- LCD_DrawLine(tx, ty-2, tx, ty-7);
- LCD_DrawLine(tx-2, ty, tx-7, ty);
- LCD_DrawLine(tx+2, ty, tx+7, ty);
- //
- // while(KEY_Scan(0))
- // KeyMode();
- DCMI_Start();
- //低字節的前5位用來表示B(BLUE)
- //低字節的后三位+高字節的前三位用來表示G(Green)
- //高字節的后5位用來表示R(RED)
- // R8 = (int) floor( R5 * 255.0 / 31.0 + 0.5);
- // G8 = (int) floor( G6 * 255.0 / 63.0 + 0.5);
- // B8 = (int) floor( R5 * 255.0 / 31.0 + 0.5);
- // R8 = (int) floor( (tempcolor>>11) * 255.0 / 31.0 + 0.5);
- // G8 = (int) floor((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5);
- // B8 = (int) floor( (tempcolor&0x1f) * 255.0 / 31.0 + 0.5);
-
- // delay_ms(1);
- }
- //RGB565測試
- //RGB數據直接顯示在LCD上面
- void fing()
- {
- u16 temptime;
- if (time<delaytime)temptime=time+201-delaytime;
- else temptime=time-delaytime;
-
- if(tempdrum[0][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_2);
- else GPIO_ResetBits(GPIOG,GPIO_Pin_2);
- if(tempdrum[1][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_4);
- else GPIO_ResetBits(GPIOG,GPIO_Pin_4);
- if(tempdrum[2][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_6);
- else GPIO_ResetBits(GPIOG,GPIO_Pin_6);
- if(tempdrum[3][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_8);
- else GPIO_ResetBits(GPIOG,GPIO_Pin_8);
- }
- void rgb565_test()
- {
- u8 effect=0,saturation=2,contrast=2;
- u8 scale=1; //默認是全尺寸縮放
- u8 msgbuf[15]; //消息緩存區
- // u8 msgbuf2[15]; //消息緩存區
- u16 tempx;
-
- LCD_Clear(BLACK);
- POINT_COLOR=RED;
- OV2640_RGB565_Mode(); //RGB565模式
- My_DCMI_Init(); //DCMI配置
- //OV2640_Window_Set(0,0,lcddev.width,lcddev.height/4);
- DCMI_DMA_Init((u32)&LCD->LCD_RAM,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置
- OV2640_ImageWin_Set((800-lcddev.width)/2,(800-lcddev.height/4)/2,lcddev.width,lcddev.height/8);//1:1真實尺寸
-
- OV2640_OutSize_Set(480,lcddev.height/8);
-
- delay_ms(800);
-
- DCMI_Start(); //啟動傳輸
-
- while(1)
- {
-
- tempx=x;
-
- getcolor(tempx,20,1);
- tempx+=wide;
- getcolor(tempx,20,2);
- tempx+=wide;
- getcolor(tempx,20,3);
- tempx+=wide;
- getcolor(tempx,20,4);
-
- fing();
- time++;
- if(time>200)time=0;
-
- if(KEY_Scan(0))
- KeyMode();
- }
- }
- int main(void)
- {
- u8 key;
- u8 t;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置系統中斷優先級分組2
- delay_init(168); //初始化延時函數
- uart_init(115200); //初始化串口波特率為115200
- usart2_init(42,115200); //初始化串口2波特率為115200
- LED_Init(); //初始化LED
- LCD_Init(); //LCD初始化
- KEY_Init(); //按鍵初始化
- FINE_Init();
- TIM3_Int_Init(10000-1,8400-1);//10Khz計數,1秒鐘中斷一次
-
- usmart_dev.init(84); //初始化USMART
- POINT_COLOR=RED;//設置字體為紅色
-
- while(OV2640_Init())//初始化OV2640
- {
- LCD_ShowString(30,130,240,16,16,"OV2640 ERR");
- delay_ms(200);
- LCD_Fill(30,130,239,170,WHITE);
- delay_ms(200);
- }
- LCD_ShowString(30,130,200,16,16,"OV2640 OK");
-
- while(1)
- {
- rgb565_test();
-
- }
- }
-
復制代碼
所有資料51hei提供下載:
攝像頭采集程序.rar
(575.18 KB, 下載次數: 61)
2018-5-22 02:13 上傳
點擊文件名下載附件
|