stm32f103+ov7670+串口传输rgb565图片到PC端并显示

2019-07-21 00:30发布

最近因为课设的缘故在做这一块,参考了很多资料后总算调试成功了,所以分享出来,有需要的朋友可以参考一下。camara_refresh函数实现在TFTLCD显示,sendpicture函数实现传输图片数据,用按键实现两者的转换。PC端用串口助手接收数据并保存为txt文件,在matlab上实现将数据转化为图片。程序基本跟正点原子的代码一样,因为TFTLCD显示屏不同,所以TFT显示函数略有区别。ov7670寄存器是参考网上的RGB565格式的配置。先看下代码:
ov7670采集图片并在TFTLCD显示:
void camera_refresh(void)
{
        u32 j;
        u16 color;
        u16 temp;

        u16 count=0;
        if(ov_sta==2)
        {
                LCD_Set_Window(0,(tftlcd_data.height-240)/2,240-1,240-1);
               
                OV7670_RRST=0;                                 
                OV7670_RCK_L;
                OV7670_RCK_H;
                OV7670_RCK_L;
                OV7670_RRST=1;                               
                OV7670_RCK_H;
                for(j=0;j<57600;j++)   
                {
                         OV7670_RCK_L;
                         color=GPIOF->IDR&0XFF;       
                         OV7670_RCK_H;
                         color<<=8;  
                         OV7670_RCK_L;
                         color|=GPIOF->IDR&0XFF;       
                         OV7670_RCK_H;
                         LCD_WriteData_Color(color);
                }               
    EXTI_ClearITPendingBit(EXTI_Line7);               
                ov_sta=0;                                       
        }
}

ov7670采集图片并用串口发送到PC:
void sendpicture(void)
{
        u16 m;
        u16 n;
        u16 color;
        u16 count=0;
        if(ov_sta==2)
        {
                LCD_Set_Window(0,(tftlcd_data.height-240)/2,240-1,240-1);
               
                OV7670_RRST=0;                               
                OV7670_RCK_L;
                OV7670_RCK_H;
                OV7670_RCK_L;
                OV7670_RRST=1;                       
                OV7670_RCK_H;
          for(m=0;m<240;m++)   
         {
                 for(n=0;n<240;n++)
                 {
                         OV7670_RCK_L;
                         color=GPIOF->IDR&0XFF;       
                         while((USART1->SR&0X40)==0);  
                         USART1->DR = color;
                         OV7670_RCK_H;
                         color<<=8;  
                         OV7670_RCK_L;
                         color|=GPIOF->IDR&0XFF;       
                         while((USART1->SR&0X40)==0);
                         USART1->DR = color;               
                         OV7670_RCK_H;
                 }
         }
   EXTI_ClearITPendingBit(EXTI_Line7);               
         ov_sta=0;       
  }
}

主函数:
int main()
{
        u8 temp = 3;
        u8 key;       
        SysTick_Init(72);
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        LED_Init();
        KEY_Init();
        USART1_Init(115200);
        TFTLCD_Init();
        while(OV7670_Init())
        {
                LCD_ShowString(10,80,tftlcd_data.width,tftlcd_data.height,16,"OV7670 Error!");
                delay_ms(200);
                LCD_Fill(10,80,239,206,WHITE);
                delay_ms(200);
        }
        LCD_ShowString(10,80,tftlcd_data.width,tftlcd_data.height,16,"OV7670 OK!     ");
        delay_ms(1500);
        EXTI7_Init();
        OV7670_Window_Set(12,174,240,240);               
        OV7670_CS=0;       
        LCD_Clear(BLACK);
        while(1)
        {               
                key=KEY_Scan(0);
                if(key == KEY_UP)
          {
                  sendpicture();
          }else
                {
                  camera_refresh();
                }
        }
}

用串口调试助手时,要先勾选DTR,选择正确的波特率,然后勾选Hex显示。此时接收窗口可能有几个数据出现,记得要先清理掉。按下按键Key_up,开始接收数据。注意观察接收的数据总数是否等于所设置图片的“宽×高×2”。在我的调试过程中,一开始我没有将TFTLCD的显示和数据的传输分开,导致串口传输的数据一直为重复的几个序列,而且传输速率很慢,LCD显示也比较慢。将两个部分分开并用按键来做功能的切换后取得了较好的成效。比较麻烦的是我没有自己编写一个上位机来接收串口数据并转化为图片,所以只能用笨方法来保存数据并用matlab来实现转化。matlab程序是参考别人的代码,直接拿过来用就可以了,运行时间也不慢。总体来说,用串口来实现图像的传输,只要你不对分辨率有太高的要求,还是可行的。
matlab程序:
length=240;width=240;//由前面设置的图片分辨率决定
in_name='ov7670.txt';
out_name='ov7670.bmp';
pic=uint8(zeros(length,width,3));

in=textread(in_name,'%s');
dec_data=hex2dec(in);
% dlmwrite('dec.txt',dec_data,'','');
% dec_test=dec_data(1:320);
k=1;
for i=1:length
for j=1:width
  H=dec_data(k,1);
  if(k+1>width*length*2)
   k=k-1;
  else
   k=k;
  end
  L=dec_data(k+1,1);
  k=k+2;
  pic(i,j,1)=(H/8)*8;%前一字节的前五位为R
  pic(i,j,2)=(mod(H,8)*8+L/32)*4;%前一字节的后三位和后一字节的前三位为G
  pic(i,j,3)=(mod(L,32))*8;%后一字节的后五位为B
end
end
figure,imshow(pic);
imwrite(pic,out_name);

效果图就放一张240*240的好了,有点糊。。。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
5条回答
15级的许同学
2019-07-21 02:57
楼主你好,我看你的数据发送只通过while((USART1->SR&0X40)==0);来判断是否发送完毕,这样串口接收助手上显示收到的程序时,不会出现数据丢失的情况吗?
    我在发送每个字节,并使用while循环,还要之后加入延时函数才能确保,串口接收助手上显示字节数目正确,不知道是发送出现丢失,还是接收端接受不及时。
     如果不加入延时函数就会出现,串口调试助手上显示接收字符个数不正确
     我采用波特率是115200

一周热门 更多>