項目設計智能車最終代碼
0.png (44.55 KB, 下載次數: 47)
下載附件
2018-2-19 03:13 上傳
單片機源程序如下:
- #include "common.h"
- #include "camera.h"
- #include "gpio.h"
- #include "exti.h"
- #include "uart.h"
- #include "roadJudge.h"
- #include "arm_math.h"
- #include "FTM.h"
- #include "delay.h"
- #include "isr.h"
- //變量定義
- unsigned char threshold;
- unsigned char Is_SendPhoto=0;
- unsigned char Pix_data[V][H]={0},Bina_data[V][H]={0};// int *p=new int[len];V=50;H=150;
- int LeftBorder[V]={0},RightBorder[V]={0}, CenterLine[V]={0};//記錄左右邊界,和中間線
- unsigned char CCD_V,CCD_H;//
- unsigned char top_line=40,top_line1=50,top_line2=48;//為什么用char型
- long count,WhiteNum;
- unsigned char width_count=50;
- unsigned char width_min=50;
- unsigned char V_count=0; //采集行計數
- unsigned char jump_point;
- unsigned char last_top;//unsigned char到底是數還是字符啊?
- unsigned char top_top_line=49;
- unsigned char THRE[20];
- long thre_sum=0;
- unsigned char thread_count;
- unsigned char center_min=30;
- unsigned char left_line,right_line;
- unsigned int left_count,right_count;
- /* unsigned char left_tiaobian=0;
- unsigned char right_tiaobian=0;
- unsigned char left_guaidian=0;
- unsigned char right_guaidian=0;
- unsigned char left_tiaobian_row=0;
- unsigned char right_tiaobian_row=0;
- unsigned char left_guaidian_row=0;
- unsigned char right_guaidian_row=0;
- */
- //攝像頭初始化
- void CameraInit()
- {
- exti_init(PORTC,1,rising_down); //行中斷,PORTC1 端口外部中斷初始化 ,上升沿觸發中斷,內部下拉,,,初始化外部中斷,內部函數,設定外部中斷(IO),
- disable_irq(89); //行中斷關閉,,,89表示irq中斷向量號
- disable_irq(90); //場中斷關閉,,,新的一幅圖像,下降沿有效
- exti_init(PORTD,1,falling_down); //場中斷,PORTD1 端口外部中斷初始化 ,下降沿觸發中斷,內部下拉
- }
- //二值化函數
- void BinaData()
- {
- int i=0,j=0;
- //count=0;
- unsigned char *p;
- for(i=0;i<V;i++)
- {
- p=Pix_data[i];
- for(j=0;j<H;j++)
- {
- if(*(p+j)>=threshold)
- {
- Bina_data[i][j]=1;
- // count++;
- }
- else Bina_data[i][j]=0;
- }
- }
- }
- //整場去燥
- void AllFilt()
- {
- count=0;
- //unsigned char sum;
- for(CCD_V=1;CCD_V<V-1;CCD_V++)
- {
- for(CCD_H=1;CCD_H<H-1;CCD_H++)
- {
- if(Bina_data[CCD_V][CCD_H]==1)
- { if((Bina_data[CCD_V-1][CCD_H]==1 || Bina_data[CCD_V+1][CCD_H]==1) && (Bina_data[CCD_V][CCD_H-1]==1 || Bina_data[CCD_V][CCD_H+1]==1))
- {
- Bina_data[CCD_V][CCD_H]=1;
- count++;
- }
- else
- Bina_data[CCD_V][CCD_H]=0;
- /* sum=0;
- sum=sum + Bina_data[CCD_V-1][CCD_H] + Bina_data[CCD_V-1][CCD_H-1] + Bina_data[CCD_V-1][CCD_H+1]
- + Bina_data[CCD_V][CCD_H-1] + Bina_data[CCD_V][CCD_H+1] + Bina_data[CCD_V+1][CCD_H+1]
- + Bina_data[CCD_V+1][CCD_H-1] + Bina_data[CCD_V+1][CCD_H];
- if(sum>=4) Bina_data[CCD_V][CCD_H]=1;
- else Bina_data[CCD_V][CCD_H]=0;
- */
- }
- else if(Bina_data[CCD_V][CCD_H]==0)
- {
- if((Bina_data[CCD_V-1][CCD_H]==0 || Bina_data[CCD_V+1][CCD_H]==0) && (Bina_data[CCD_V][CCD_H-1]==0 || Bina_data[CCD_V][CCD_H+1]==0))
- {
- Bina_data[CCD_V][CCD_H]=0;
- }
- else
- {
- Bina_data[CCD_V][CCD_H]=1;
- count++;
- }
- /*sum=0;
- sum=sum + Bina_data[CCD_V-1][CCD_H] + Bina_data[CCD_V-1][CCD_H-1] + Bina_data[CCD_V-1][CCD_H+1]
- + Bina_data[CCD_V][CCD_H-1] + Bina_data[CCD_V][CCD_H+1] + Bina_data[CCD_V+1][CCD_H+1]
- + Bina_data[CCD_V+1][CCD_H-1] + Bina_data[CCD_V+1][CCD_H];
- if(sum<=6) Bina_data[CCD_V][CCD_H]=0;
- else Bina_data[CCD_V][CCD_H]=1;*/
- }
- }
- }
- }
- //統計圖像下半部分白點數
- void WhiteCount()
- {
- WhiteNum=0;
- for(CCD_V=0;CCD_V<25;CCD_V++)
- for(CCD_H=0;CCD_H<H;CCD_H++)
- if(Bina_data[CCD_V][CCD_H]==1)
- WhiteNum++;
- }
- //中心線提取,,,480*640,LINE去除掉起始行
- void get_center()
- {
-
- unsigned char *p;
- static unsigned char last_center=75;
- for(CCD_V=0;CCD_V<LINE;CCD_V++)//,,,為什么是前五行,視野最前方提取有何意義
- {
- p=Bina_data[CCD_V];
- for(CCD_H=75;CCD_H>1;CCD_H--)//中間往右
- {
- if((*(p+CCD_H)==0) && (*(p+CCD_H-1)==0) && (*(p+CCD_H-2)==0)) //右邊黑線檢測,,,連續三列為黑
- {
- RightBorder[CCD_V]=CCD_H;//記錄列數
- break;//找到該行的左邊界
- }
- else RightBorder[CCD_V]=0; //如果右邊沒有檢測到有黑線
-
- }
-
- for(CCD_H=75;CCD_H<H-2;CCD_H++) //中間往左
- {
- if((*(p+CCD_H)==0) && (*(p+CCD_H+1)==0) && (*(p+CCD_H+2)==0)) //左邊黑線檢測
- {
- LeftBorder[CCD_V]=CCD_H;
- break;
- }
- else LeftBorder[CCD_V]=149; //如果左邊沒有檢測到有黑線
-
- }
- CenterLine[CCD_V]=(LeftBorder[CCD_V]+RightBorder[CCD_V])/2; //計算中心線
-
- if(fabsf(CenterLine[4]-last_center)>=8) //基準,,,第五行有什么用?
- CenterLine[4]=last_center;
- last_center=CenterLine[4];
-
- if((LeftBorder[CCD_V]-RightBorder[CCD_V])>width_count) //判斷賽道寬度,CCD_V=4
- width_count=LeftBorder[CCD_V]-RightBorder[CCD_V];//width_count最大值, CenterLine記錄中間線, CenterLine[4]有什么特殊的?
-
- }
-
- for(CCD_V=LINE;CCD_V<V;CCD_V++)
- {
- p=Bina_data[CCD_V];
- for(CCD_H=(unsigned char )CenterLine[CCD_V-1];CCD_H>1;CCD_H--)//中間往右,,,為什么是四行的中間點,而不是75?
- {
- if((*(p+CCD_H)==0) && (*(p+CCD_H-1)==0) && (*(p+CCD_H-2)==0)) //右邊黑線檢測
- {
- RightBorder[CCD_V]=CCD_H;
- break;
- }
- else RightBorder[CCD_V]=0;
-
- }
-
- for(CCD_H=(unsigned char )CenterLine[CCD_V-1];CCD_H<H-2;CCD_H++) //中間往左,,,,能增加運算速度
- {
- if((*(p+CCD_H)==0) && (*(p+CCD_H+1)==0) && (*(p+CCD_H+2)==0)) //左邊黑線檢測
- {
- LeftBorder[CCD_V]=CCD_H;
- break;
- }
- else LeftBorder[CCD_V]=149;
-
- }
- CenterLine[CCD_V]=(LeftBorder[CCD_V]+RightBorder[CCD_V])/2;
-
-
- if((LeftBorder[CCD_V]-RightBorder[CCD_V])>width_count) ////判斷賽道寬度
- width_count=LeftBorder[CCD_V]-RightBorder[CCD_V];//這真的是判斷賽道寬度嘛?這簡直在找最寬的賽道嘛?
-
- }
- }
- //
- void centeradjust()
- {
- for(CCD_V=top_line-1;CCD_V<V;CCD_V++)//四十行開始往上
- {
- if(LeftBorder[top_line-2]>=145 || LeftBorder[top_line-3]>=145)//如果上兩行的左邊界有一個大于145,(其實右邊界),調整思路是什么?
- {
- CenterLine[CCD_V]= (int)((147-left_offset_row)*1.0/(V-1-top_line)*(CCD_V+2-top_line)+0.5)+
- left_offset_row; //這一堆可能在矯正些什么
- if(CenterLine[CCD_V]>=147) CenterLine[CCD_V]=147;//左邊界最大到147,
- }
-
- if(RightBorder[top_line-2]<=5 || RightBorder[top_line-3]<=5)
- {
- CenterLine[CCD_V]=(int)((2-right_offset_row)*1.0/(V-1-top_line)*(CCD_V+2-top_line)+0.5)+right_offset_row;//右邊界的矯正
- if(CenterLine[CCD_V]<=3) CenterLine[CCD_V]=2;
- }
- }
-
-
- }
- //起跑線,有點迷?
- void stop_line()
- {
- Right_dot=0;
- left_dot=0;
-
- if(stop_flag==1)
- {
- for(CCD_V=10;CCD_V<15;CCD_V++)
- {
- for(CCD_H=RightBorder[20];CCD_H<=CenterLine[20];CCD_H++)
- {
- if(Bina_data[CCD_V][CCD_H]==0)//為何不統計寬度?統計勞什子的黑點數
- Right_dot++;
- }
- for(CCD_H=CenterLine[20];CCD_H<=LeftBorder[20];CCD_H++)
- {
- if(Bina_data[CCD_V][CCD_H]==0)
- left_dot++;
- }
- if((LeftBorder[CCD_V]-RightBorder[CCD_V])<width_min)
- width_min=LeftBorder[CCD_V]-RightBorder[CCD_V]; //有點蒙了
- }
- if(Right_dot>=30 && Right_dot<=90 && left_dot<=90 && left_dot>=30 && top_line1>=45)
- {
- FTM_PWM_Duty(FTM0,CH4,1000);//要減速嘛?4,5通道是干嘛的?
- FTM_PWM_Duty(FTM0,CH5,0);
- if(gpio_get(PORTA,13)==0) delayms(50);//PORTA是干啥的?
- if(gpio_get(PORTA,14)==0) delayms(50);
- if(gpio_get(PORTA,15)==0) delayms(50);
- if(gpio_get(PORTA,16)==0) delayms(50);
- if(gpio_get(PORTA,12)==0) delayms(50);
- gpio_set(PORTC,19,0);
- }
- }
- }
- //中心線判斷與矯正 頂端行求取,,,圖像的模糊
- void TopGet()
- {
-
- for(CCD_V=8;CCD_V<V-2;CCD_V++)//又從第八行開始干啥?
- {
- if((CenterLine[CCD_V]-CenterLine[CCD_V+1])>center_error || (CenterLine[CCD_V+1]-CenterLine[CCD_V])>center_error) //中線誤差三?突變嘛?
- {
- if((CenterLine[CCD_V+1]-CenterLine[CCD_V+2])>center_error || (CenterLine[CCD_V+2]-CenterLine[CCD_V+1])>center_error)//連續兩行突變?
- {
- top_line1=CCD_V;//又干啥呀?
- break;
- }
- else ;
- }
- else
- top_line1=48;//這樣啊
- if(LeftBorder[CCD_V]-RightBorder[CCD_V]<=30)
- {
- if(LeftBorder[CCD_V+1]-RightBorder[CCD_V+1]<=30)
- {
- top_line2=CCD_V;//30是允許通過行駛的寬度嘛?
- break;
- }
- else ;
- }
- }
- if(top_line1>=30 && top_line2>=30)
- top_line=(top_line2 < top_line1) ? top_line2 : top_line1;//找個最小的
-
- /*
- if(count>=5100)
- last_top=top_line;*/
- }
- void line_count()
- {
- left_line=0;
- right_line=0;
- for(CCD_V=0;CCD_V<49;CCD_V++)
- {
- if(LeftBorder[CCD_V]==149)
- left_line++;
- if(RightBorder[CCD_V]==0)
- right_line++;
- }
- }
- //十字交叉,,,沒看太明白
- void CrossJudge()
- {
- if(count>=5000 && count<=5800 && right_line>=10 && left_line>=10)// && right_line<=18 && left_line<=18),,,count什么呀?
- {
- for(CCD_V=8;CCD_V<49;CCD_V++)
- {
- if(CenterLine[8]+CenterLine[7]-CenterLine[1]-CenterLine[0]<0)
- {
- if(LeftBorder[CCD_V] - LeftBorder[CCD_V-1]>= 3)
- {
- LeftBorder[CCD_V]=LeftBorder[CCD_V-1]-1;
- RightBorder[CCD_V]=RightBorder[5];
- }
- else if(LeftBorder[CCD_V]>=145)
- LeftBorder[CCD_V]=LeftBorder[CCD_V-1];
- else;
- }
-
- else if(CenterLine[8]+CenterLine[7]-CenterLine[1]-CenterLine[0]>0)
- {
- if(RightBorder[CCD_V] - RightBorder[CCD_V-1]<= -3)
- {
- RightBorder[CCD_V]=RightBorder[CCD_V-1]+1;
- LeftBorder[CCD_V]=LeftBorder[5];
- }
- else if(RightBorder[CCD_V]<= 5)
- RightBorder[CCD_V]=RightBorder[CCD_V-1];
- else;
- }
- CenterLine[CCD_V]=(LeftBorder[CCD_V]+RightBorder[CCD_V])/2;
- }
-
- for(CCD_V=49;CCD_V>top_line;CCD_V--)
- {
- for(CCD_H=CenterLine[top_line];CCD_H>RightBorder[top_line];CCD_H--)
- {
- if(Bina_data[CCD_V][CCD_H+1]==1 && Bina_data[CCD_V][CCD_H]==1)
- {
- if(Bina_data[CCD_V][CCD_H-1]==0 && Bina_data[CCD_V][CCD_H-2]==0)
- {
- RightBorder[CCD_V]=CCD_H;
- break;
- }
- }
- else RightBorder[CCD_V]=RightBorder[top_line];
- }
- for(CCD_H=CenterLine[top_line];CCD_H<LeftBorder[top_line];CCD_H++)
- {
- if(Bina_data[CCD_V][CCD_H+1]==1 && Bina_data[CCD_V][CCD_H]==1)
- {
- if(Bina_data[CCD_V][CCD_H+3]==0 && Bina_data[CCD_V][CCD_H+2]==0)
- {
- LeftBorder[CCD_V]=CCD_H;
- break;
- }
- }
- else LeftBorder[CCD_V]=LeftBorder[top_line];
- }
- CenterLine[CCD_V]=(LeftBorder[CCD_V]+RightBorder[CCD_V])/2;
- }
-
- for(CCD_V=48;CCD_V>=top_line;CCD_V--)
- {
- if((CenterLine[CCD_V]-CenterLine[CCD_V-1])>center_error || (CenterLine[CCD_V-1]-CenterLine[CCD_V])>center_error)
- {
- if((CenterLine[CCD_V]-CenterLine[CCD_V-2])>center_error || (CenterLine[CCD_V-2]-CenterLine[CCD_V])>center_error)
- {
- top_top_line=CCD_V;
- break;
- }
- else ;
- }
- }
-
- //中心線修正
-
- }
- }
-
- //=====================================
- //|| ||
- //|| 十字道處理 ||
- //|| ||
- //=====================================
- /* crossJudge()
- {
- char i,j;
- char left_tiaobian=0;
- char right_tiaobian=0;
- char left_guaidian=0;
- char right_guaidian=0;
- char left_tiaobian_row=0;
- char right_tiaobian_row=0;
- char left_guaidian_row=0;
- char right_guaidian_row=0;
-
-
- if(count>=5000 && count<=5800 && right_line>=10 && left_line>=10) //十字道判斷條件1,整場黑點數2,白條寬度 3,斜十字能否準確判斷!
- {
-
- //==========十字道處理========== //搜索左下邊沿
- for(i=1;i<V;i++) //注意不要讓數組溢出
- {
- //====左邊線處理==
- //搜索拐點 //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7?
- //左右要寫的一樣
- if(LeftBorder[i]>LeftBorder[i-1] || LeftBorder[i]>140) //抓住十字邊界的延生特點左突變
- {
- left_guaidian= LeftBorder[i-3];
- left_guaidian_row=i-3;
- break;
- }
-
- }
- //搜索跳變點 //搜索左上邊沿
- for(i=1;i<V;i++)
- {
- if(LeftBorder[i]-LeftBorder[i-1]<-10)
- {
-
- left_tiaobian= LeftBorder[i+2];
- left_tiaobian_row=i+2;
- break;
- }
- }
- //搜索完后再補線。
- //邊線補線
- if((left_guaidian!=0)&&(left_tiaobian!=0)) //通過直線去補線效果更好
- {
- for(i=left_guaidian_row;i<=left_tiaobian_row;i++)
- LeftBorder[i]=(char)((left_tiaobian- left_guaidian)*1.0/( left_tiaobian_row-left_guaidian_row)*(i-left_guaidian_row)+0.5)+ left_guaidian;
-
-
- }
-
- //====右邊線處理==
- //搜索拐點
- for(i=1;i<V;i++) //注意不要讓數組溢出
- {
- //====右邊線處理==
- //搜索拐點 //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7?
- //左右要寫的一樣
- if(RighttBorder[i]<RightBorder[i-1] || RightBorder[i]<10) //抓住十字邊界的延生特點左突變
- {
- right_guaidian= RightBorder[i-3];
- right_guaidian_row=i-3;
- break;
- }
-
- }
- //搜索跳變點 //搜索右上邊沿
- for(i=1;i<V;i++)
- {
- if( RightBorder[i]- RightBorderr[i-1]>10)
- {
-
- right_tiaobian= RightBorder[i+2];
- right_tiaobian_row=i+2;
- break;
- }
- }
- //邊線補線
- if((right_guaidian!=0)&&(right_tiaobian!=0))
- {
- for(i=right_guaidian_row;i<right_tiaobian_row-1;i++)
- RightBorder[i]=(char)(( right_tiaobian-right_guaidian)*1.0/( right_tiaobian_row- right_guaidian_row)*(i-right_guaidian_row)+0.5)+right_guaidian;
- }
-
-
-
- }
- //=================中心線重提取============
-
-
- for(i=0;i<V;i++)
-
- CenterLine[i]=(LeftBorder[i]+RightBorder[i])/2;
-
- }*/
- //小S
- void S_road()
- {
- long center_sum=0;
- //long left_sum=0,right_sum=0;
- // unsigned char left_ave=0,right_ave=0;
- if(count>5800)
- {
- for(CCD_V=5;CCD_V<=40;CCD_V++)
- {
- if(fabsf((LeftBorder[CCD_V]-LeftBorder[CCD_V+1])>=3)) LeftBorder[CCD_V]=LeftBorder[CCD_V-1];
- if(fabsf(RightBorder[CCD_V]-RightBorder[CCD_V+1])>=3) RightBorder[CCD_V]=RightBorder[CCD_V-1];
- CenterLine[CCD_V]=(LeftBorder[CCD_V]+RightBorder[CCD_V])/2;
- center_sum+=CenterLine[CCD_V];
- //right_sum+=RightBorder[CCD_V];
- //left_sum+=LeftBorder[CCD_V];
- }
- //left_ave=left_sum/19;
- //right_ave=right_sum/19;
-
-
- for(CCD_V=5;CCD_V<=44;CCD_V++)
- {
- CenterLine[CCD_V]=center_sum/35;//好吧,中線變直線了,完美
- /* if((right_line-left_line)>5)
- CenterLine[CCD_V]=CenterLine[CCD_V]-10;
- if((left_line-right_line)>5)
- CenterLine[CCD_V]=CenterLine[CCD_V]+10;*/
- }
-
- }
-
- }
- //發送圖像到上位機
- void send_photo()
- {
- int i=0,j=0;
- //以下四句話是固定格式,是串口和上位機軟件之間的協議
- uart_putchar(UART2,0);
- uart_putchar(UART2,255);
- uart_putchar(UART2,1);
- uart_putchar(UART2,0);
- for(i=V-1;i>=0;i--)
- for(j=H-1;j>=0;j--)
- {
- if(j==CenterLine[i]) uart_putchar(UART2,0); //中心線
- else if(j==RightBorder[i]) uart_putchar(UART2,0);
- else if(j==LeftBorder[i]) uart_putchar(UART2,0);
- else uart_putchar(UART2,Bina_data[i][j]);
- }
- }
- void SendImg()
- {
- disable_irq(89);
- disable_irq(90); //關閉場中斷,防止串口發送圖像數據進程被打亂
- if(gpio_get(PORTA,11)==0) thread();
- else threshold=135;
- BinaData();
-
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
K60 smartcar最終代碼.rar
(1.83 MB, 下載次數: 33)
2018-2-18 11:32 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|