一、雷达概述
雷达(Radio Detection and Ranging,无线电探测与测距)是一种利用电磁波探测目标位置、速度等信息的主动式传感器系统。其基本原理是发射电磁波并接收目标反射的回波,通过分析回波的时间差、频率变化等参数,实现对目标的探测、跟踪和识别。
军用雷达:预警雷达(如远程防空)、火控雷达(导弹制导)、侦察雷达。
民用雷达:气象雷达(降水监测)、航空管制雷达、汽车防撞雷达、地质探测雷达
应用领域:
军事:防空系统(如爱国者导弹)、战斗机火控、舰船导航。
航空:机场空中交通管制(ATC)、飞机防撞系统(TCAS)。
气象:监测风暴、降水、风场(如多普勒天气雷达)。
交通:汽车自动驾驶(毫米波雷达)、铁路障碍物检测。
科研:天文观测(射电望远镜)、行星探测(如火星雷达)。
二、制作目标
以STM32F103C8T6单片机为主控,使用cubemx平台开发,SG90舵机+HC-SR04超声波模块往复转动180度扫描周围的物体,在2.4寸TFT-LCD(320×240)屏显示雷达图,检测到周围的物体后,在LCD屏雷达图画点显示物体的位置角度和距离,模拟真实雷达的工作原理。
三、实物效果
四、物料清单
1、SG90+超声波+云台支架全套
商品详情
2、2.4寸TFT液晶屏ILI9341驱动240*320模块LCD触摸SPI
https://item.taobao.com/item.htm?id=679175996067&pisk=gS8L_S2XCAD3hWTdsBogEUCBA_lGycAe_pRbrTX3Vdp9eIFHxgXlVap2HgaoYwjRyd6M-9AhR_sWEKthdHXuyUpwpy4lRL0RFI-Za9fH-7CWfpUkxBXHX7QeSH4lKv7JNKb-nx0moBRF7aMmnOfzn1bfiua7E6s1CafJjBZ3GBRFzTNgFmx6T7LGjnF5NTGO5_CcFasCFl_1Q_qCFL6CfR1Aga_WF96_565bRu1CPGGOMsPCOy1I5V1ANuwBFaG91O55P695Pv6seONCEzKcFaYJil287P8O9MB8rOzRMeUcftGOCzURp_ILxB6TPzT9bg0879i4sT7hLECpUqzFRgK2Z_pKJy9JgFJO1Kg8o9OwinjeRqrPDw6NqeOiDrQBL_IfPGF7PCQFdK81lqwO_hOHVeJLwz1e-EjR3Gh7zgb6oitXp7l21w1WUi8o3yWBNI82mZ3gAZO9VKKR4h8DkBLunIP4AfhT4uSC_FoPVShrkPcR6tcKyurPbf5OnfhT4uSC_1Bm9bEz4GlN.&spm=tbpc.boughtlist.suborder_itemtitle.1.12932e8d8xCDO2&skuId=5666470206563 3、STM32F103C8T6最小系统板
商品详情
五、原理图和接线说明
1、原理图
2、接线说明
需要注意的是:系统连接完成后,必须用TypeC口供电,否则用下载器供电不能同时带起来LCD屏和舵机,会出现LCD屏白屏闪烁的问题。
LCD显示引脚:
VCC --> 3.3V
GND --> GND
CS --> PB11
Reset --> PB12
DC --> PB10
SDI --> PB15
SCK --> PB13
LED --> PB9
HC-SR04引脚:
VCC --> 5.0V
GND --> GND
Trig --> PA5
Echo --> PA0
SG90引脚:
VCC --> 5.0V
GND --> GND
PWM(信号线) --> PA6
六、软件设计过程
1、cubemx配置
(1)时钟和系统
(2)GPIO配置:PA5用于输出超声波传感器的发射信号,PB9、PB10、PB11、PB12用于LCD屏的控制
(3)定时器配置:TIM1用于产生微秒延时产生超声波的发射信号,TIM2用于捕获超声波收到的信号从而计算出距离物体的距离,TIM3用于产生PWM波用于控制舵机的转动
数据参数意义:
此时产生PWM波形频率:72M / (719 +1)/ (1999+1) = 50Hz
定时器周期:1/50 = 20ms
(4)SPI设置 :用于与LCD屏的通讯
(5)时钟树
2、程序代码
(1)main函数
int main(void)
{/* USER CODE BEGIN 1 */int i=50;double k;int d;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_SPI2_Init();MX_TIM1_Init();MX_TIM2_Init();MX_TIM3_Init();/* USER CODE BEGIN 2 */Lcd_Init();//LCD屏初始化LCD_LED_SET;//通过IO控制背光LCD_RST_SET;Lcd_Clear(BLACK);//画雷达图radar_picture(); Hcsr04Init(&htim2, TIM_CHANNEL_1);//超声波测距初始化Hcsr04Start();HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//***初始化定时器,用于舵机的控制/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(i==50){ for(i=50;i<250;i++){ Hcsr04Start();d = (int)Hcsr04Read()*152/100;//将超声波测得的距离投射在LCD屏上的距离if(d>152) //测距越界{d=155;}LCD_Showdecimal(63,215,Hcsr04Read(),3,2,16);//LCD屏显示超声波的距离LCD_ShowNum(65,5,(double)(i-50)/200*180,3);//LCD屏显示旋转角度__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,i); //舵机运动 HAL_Delay(100);Radarline2((double)((i-50)*180/200),d);//在LCD屏画出超声波检测到物体的点// Radarline((double)((i-50)*180/200),(int)Hcsr04Read()*152/300); }}if(i==250){ for(i=250;i>50;i--){ Hcsr04Start();d = (int)Hcsr04Read()*152/100;if(d>152) //测距越界{d=155;}LCD_Showdecimal(63,215,Hcsr04Read(),3,2,16);LCD_ShowNum(65,5,(double)(i-50)/200*180,3);// Radarline((double)((i-50)*180/200),(int)Hcsr04Read()*152/200);// Radarline((double)((i-50)*180/200),120);__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,i); //舵机运动 HAL_Delay(100); Radarline2((double)((i-50)*180/200),d);// Radarline((double)((i-50)*180/200),(int)Hcsr04Read()*152/300); }}// LCD_Showdecimal(63,215,Hcsr04Read(),3,2,16);// Gui_DrawFont_GBK16(200,219,GREEN,BLACK,"cm"); // HAL_Delay(100); }/* USER CODE END 3 */
}
(2) hc-sr04.c
#include "hc-sr04.h"
#include "tim.h"Hcsr04InfoTypeDef Hcsr04Info;/*** @description: ??????????????????* @param {TIM_HandleTypeDef} *htim* @param {uint32_t} Channel* @return {*}*/
void Hcsr04Init(TIM_HandleTypeDef *htim, uint32_t Channel)
{/*--------[ Configure The HCSR04 IC Timer Channel ] */// MX_TIM2_Init(); // cubemx???Hcsr04Info.prescaler = htim->Init.Prescaler; // 72-1Hcsr04Info.period = htim->Init.Period; // 65535Hcsr04Info.instance = htim->Instance; // TIM2Hcsr04Info.ic_tim_ch = Channel;if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_1){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_1; // TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_2){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_2; // TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_3){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_3; // TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_4){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_4; // TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_4){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_4; // TIM_CHANNEL_4}/*--------[ Start The ICU Channel ]-------*/HAL_TIM_Base_Start_IT(htim);HAL_TIM_IC_Start_IT(htim, Channel);
}/*** @description: HC-SR04??* @param {*}* @return {*}*/
void Hcsr04Start()
{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);Tims_delay_us(10); // 10us延迟HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
}/*** @description: ?????????????* @param {*} main.c????void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)* @return {*}*/
void Hcsr04TimOverflowIsr(TIM_HandleTypeDef *htim)
{if(htim->Instance == Hcsr04Info.instance) // TIM2{Hcsr04Info.tim_overflow_counter++;}
}/*** @description: ???????????->??* @param {*} main.c????void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)* @return {*}*/
void Hcsr04TimIcIsr(TIM_HandleTypeDef* htim)
{if((htim->Instance == Hcsr04Info.instance) && (htim->Channel == Hcsr04Info.active_channel)){if(Hcsr04Info.edge_state == 0) // ?????{// ?????????T1,???????????Hcsr04Info.t1 = HAL_TIM_ReadCapturedValue(htim, Hcsr04Info.ic_tim_ch);__HAL_TIM_SET_CAPTUREPOLARITY(htim, Hcsr04Info.ic_tim_ch, TIM_INPUTCHANNELPOLARITY_FALLING);Hcsr04Info.tim_overflow_counter = 0; // ??????????Hcsr04Info.edge_state = 1; // ????????????}else if(Hcsr04Info.edge_state == 1) // ?????{// ???????T2,????????Hcsr04Info.t2 = HAL_TIM_ReadCapturedValue(htim, Hcsr04Info.ic_tim_ch);Hcsr04Info.t2 += Hcsr04Info.tim_overflow_counter * Hcsr04Info.period; // ???????????Hcsr04Info.high_level_us = Hcsr04Info.t2 - Hcsr04Info.t1; // ??????? = ?????? - ??????// ????Hcsr04Info.distance = (Hcsr04Info.high_level_us / 1000000.0) * 340.0 / 2.0 * 100.0;// ?????????Hcsr04Info.edge_state = 0; // ??????,??__HAL_TIM_SET_CAPTUREPOLARITY(htim, Hcsr04Info.ic_tim_ch, TIM_INPUTCHANNELPOLARITY_RISING);}}
}/*** @description: ???? * @param {*}* @return {*}*/
float Hcsr04Read()
{// ??????if(Hcsr04Info.distance >= 500){Hcsr04Info.distance = 500;}return Hcsr04Info.distance;
}///**
// * @brief ?????us,Prescaler -> 32-1
// * @param us: <= 65535
// * @retval None
// */
//void Tims_delay_us(uint16_t nus)
//{
// __HAL_TIM_SET_COUNTER(DLY_TIM_Handle, 0);
// __HAL_TIM_ENABLE(DLY_TIM_Handle);
// while (__HAL_TIM_GET_COUNTER(DLY_TIM_Handle) < nus)
// {
// }
// __HAL_TIM_DISABLE(DLY_TIM_Handle);
//}
(3) lcd.c LCD屏的驱动代码
#include "lcd.h"
#include "spi.h"
#include "gpio.h"/****************************************************************************
* 名 称:void SPIv_WriteData(u8 Data)
* 功 能:STM32_模拟SPI写一个字节数据底层函数
* 入口参数:Data
* 出口参数:无
* 说 明:STM32_模拟SPI读写一个字节数据底层函数
****************************************************************************/
//void SPIv_WriteData(u8 Data)
//{
// unsigned char i=0;
// for(i=8;i>0;i--)
// {
// if(Data&0x80)
// {
// LCD_SDA_SET; //????
// }
// else
// {
// LCD_SDA_CLR;
// }
// LCD_SCL_CLR;
// LCD_SCL_SET;
// Data<<=1;
// }
//}void SPIv_WriteData(u8 Data)
{SPI_WriteByte(&Data, 1);
}/****************************************************************************
* 名 称:Lcd_WriteIndex(u8 Index)
* 功 能:向液晶屏写一个8位指令
* 入口参数:Index 寄存器地址
* 出口参数:无
* 说 明:调用前需先选中控制器,内部函数
****************************************************************************/
void Lcd_WriteIndex(u8 Index)
{LCD_CS_CLR;LCD_RS_CLR;SPIv_WriteData(Index);LCD_CS_SET;
}/****************************************************************************
* 名 称:Lcd_WriteData(u8 Data)
* 功 能:向液晶屏写一个8位数据
* 入口参数:dat 寄存器数据
* 出口参数:无
* 说 明:向控制器指定地址写入数据,内部函数
****************************************************************************/
void Lcd_WriteData(u8 Data)
{LCD_CS_CLR;LCD_RS_SET;SPIv_WriteData(Data);LCD_CS_SET;
}/****************************************************************************
* 名 称:void LCD_WriteReg(u8 Index,u16 Data)
* 功 能:写寄存器数据
* 入口参数:Index,Data
* 出口参数:无
* 说 明:本函数为组合函数,向Index地址的寄存器写入Data值
****************************************************************************/
void LCD_WriteReg(u8 Index,u16 Data)
{Lcd_WriteIndex(Index);Lcd_WriteData_16Bit(Data);
}/****************************************************************************
* 名 称:void Lcd_WriteData_16Bit(u16 Data)
* 功 能:向液晶屏写一个16位数据
* 入口参数:Data
* 出口参数:无
* 说 明:向控制器指定地址写入一个16位数据
****************************************************************************/
void Lcd_WriteData_16Bit(u16 Data)
{ LCD_CS_CLR;LCD_RS_SET;Lcd_WriteData(Data>>8);Lcd_WriteData(Data);LCD_CS_SET;
}/****************************************************************************
* 名 称:void Lcd_Reset(void)
* 功 能:液晶硬复位函数
* 入口参数:无
* 出口参数:无
* 说 明:液晶初始化前需执行一次复位操作
****************************************************************************/
void Lcd_Reset(void)
{LCD_RST_CLR;HAL_Delay(100);LCD_RST_SET;HAL_Delay(50);LCD_LED_SET;
}void Lcd_Init(void)
{ Lcd_Reset(); //Reset before LCD Init.//2.2inch TM2.2-G2.2 Init 20171020 Lcd_WriteIndex(0x11); Lcd_WriteData(0x00); Lcd_WriteIndex(0xCF); Lcd_WriteData(0X00); Lcd_WriteData(0XC1); Lcd_WriteData(0X30);Lcd_WriteIndex(0xED); Lcd_WriteData(0X64); Lcd_WriteData(0X03); Lcd_WriteData(0X12);Lcd_WriteData(0X81);Lcd_WriteIndex(0xE8); Lcd_WriteData(0X85); Lcd_WriteData(0X11); Lcd_WriteData(0X78);Lcd_WriteIndex(0xF6); Lcd_WriteData(0X01); Lcd_WriteData(0X30); Lcd_WriteData(0X00);Lcd_WriteIndex(0xCB); Lcd_WriteData(0X39); Lcd_WriteData(0X2C); Lcd_WriteData(0X00);Lcd_WriteData(0X34);Lcd_WriteData(0X05);Lcd_WriteIndex(0xF7); Lcd_WriteData(0X20); Lcd_WriteIndex(0xEA); Lcd_WriteData(0X00); Lcd_WriteData(0X00); Lcd_WriteIndex(0xC0); Lcd_WriteData(0X20); Lcd_WriteIndex(0xC1); Lcd_WriteData(0X11); Lcd_WriteIndex(0xC5); Lcd_WriteData(0X31); Lcd_WriteData(0X3C); Lcd_WriteIndex(0xC7); Lcd_WriteData(0XA9); Lcd_WriteIndex(0x3A); Lcd_WriteData(0X55); Lcd_WriteIndex(0x36); #if USE_HORIZONTALLcd_WriteData(0xE8);//横屏参数#elseLcd_WriteData(0x48);//竖屏参数 #endifLcd_WriteIndex(0xB1); Lcd_WriteData(0X00); Lcd_WriteData(0X18); Lcd_WriteIndex(0xB4); Lcd_WriteData(0X00); Lcd_WriteData(0X00); Lcd_WriteIndex(0xF2); Lcd_WriteData(0X00); Lcd_WriteIndex(0x26); Lcd_WriteData(0X01); Lcd_WriteIndex(0xE0); Lcd_WriteData(0X0F); Lcd_WriteData(0X17); Lcd_WriteData(0X14); Lcd_WriteData(0X09); Lcd_WriteData(0X0C); Lcd_WriteData(0X06); Lcd_WriteData(0X43); Lcd_WriteData(0X75); Lcd_WriteData(0X36); Lcd_WriteData(0X08); Lcd_WriteData(0X13); Lcd_WriteData(0X05); Lcd_WriteData(0X10); Lcd_WriteData(0X0B); Lcd_WriteData(0X08); Lcd_WriteIndex(0xE1); Lcd_WriteData(0X00); Lcd_WriteData(0X1F); Lcd_WriteData(0X23); Lcd_WriteData(0X03); Lcd_WriteData(0X0E); Lcd_WriteData(0X04); Lcd_WriteData(0X39); Lcd_WriteData(0X25); Lcd_WriteData(0X4D); Lcd_WriteData(0X06); Lcd_WriteData(0X0D); Lcd_WriteData(0X0B); Lcd_WriteData(0X33); Lcd_WriteData(0X37); Lcd_WriteData(0X0F); Lcd_WriteIndex(0x29);
}/*************************************************
函数名:LCD_Set_XY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(u16 Xpos, u16 Ypos)
{ Lcd_WriteIndex(0x2A);Lcd_WriteData_16Bit(Xpos);Lcd_WriteIndex(0x2B);Lcd_WriteData_16Bit(Ypos);Lcd_WriteIndex(0x2c);
}
/*************************************************
函数名:LCD_Set_Region
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:xy起点和终点
返回值:无
*************************************************/
//设置显示窗口
void Lcd_SetRegion(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{Lcd_WriteIndex(0x2A);Lcd_WriteData_16Bit(xStar);Lcd_WriteData_16Bit(xEnd);Lcd_WriteIndex(0x2B);Lcd_WriteData_16Bit(yStar);Lcd_WriteData_16Bit(yEnd);Lcd_WriteIndex(0x2c);
}/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:xy坐标和颜色数据
返回值:无
*************************************************/
void Gui_DrawPoint(u16 x,u16 y,u16 Data)
{Lcd_SetXY(x,y);Lcd_WriteData_16Bit(Data);} /*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色COLOR
返回值:无
*************************************************/
void Lcd_Clear(u16 Color)
{ unsigned int i;Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);LCD_CS_CLR;LCD_RS_SET; for(i=0;i<X_MAX_PIXEL*Y_MAX_PIXEL;i++){
// Lcd_WriteData_16Bit(Color);SPIv_WriteData(Color>>8);SPIv_WriteData(Color);} LCD_CS_SET;
}
(4)LCDAPI.c LCD雷达图的绘制封装代码
#include "LCDAPI.h"
#include "lcd.h"
#include "font.h"
#include "oledfont.h"
#include "bmp.h"u16 BACK_COLOR, POINT_COLOR;
//从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
//通过该函数转换
//c:GBR格式的颜色值
//返回值:RGB格式的颜色值
u16 LCD_BGR2RGB(u16 c)
{u16 r,g,b,rgb; b=(c>>0)&0x1f;g=(c>>5)&0x3f;r=(c>>11)&0x1f; rgb=(b<<11)+(g<<5)+(r<<0); return(rgb);}void Gui_Circle(u16 X,u16 Y,u16 R,u16 fc)
{//Bresenham算法 unsigned short a,b; int c; a=0; b=R; c=3-2*R; while (a<b) { Gui_DrawPoint(X+a,Y+b,fc); // 7 Gui_DrawPoint(X-a,Y+b,fc); // 6 Gui_DrawPoint(X+a,Y-b,fc); // 2 Gui_DrawPoint(X-a,Y-b,fc); // 3 Gui_DrawPoint(X+b,Y+a,fc); // 8 Gui_DrawPoint(X-b,Y+a,fc); // 5 Gui_DrawPoint(X+b,Y-a,fc); // 1 Gui_DrawPoint(X-b,Y-a,fc); // 4 if(c<0) c=c+4*a+6; else { c=c+4*(a-b)+10; b-=1; } a+=1; } if (a==b) { Gui_DrawPoint(X+a,Y+b,fc); Gui_DrawPoint(X+a,Y+b,fc); Gui_DrawPoint(X+a,Y-b,fc); Gui_DrawPoint(X-a,Y-b,fc); Gui_DrawPoint(X+b,Y+a,fc); Gui_DrawPoint(X-b,Y+a,fc); Gui_DrawPoint(X+b,Y-a,fc); Gui_DrawPoint(X-b,Y-a,fc); } }
//画线函数,使用Bresenham 画线算法
void Gui_DrawLine(u16 x0, u16 y0,u16 x1, u16 y1,u16 Color)
{
int dx, // difference in x'sdy, // difference in y'sdx2, // dx,dy * 2dy2, x_inc, // amount in pixel space to move during drawingy_inc, // amount in pixel space to move during drawingerror, // the discriminant i.e. error i.e. decision variableindex; // used for looping Lcd_SetXY(x0,y0);dx = x1-x0;//计算x距离dy = y1-y0;//计算y距离if (dx>=0){x_inc = 1;}else{x_inc = -1;dx = -dx; } if (dy>=0){y_inc = 1;} else{y_inc = -1;dy = -dy; } dx2 = dx << 1;dy2 = dy << 1;if (dx > dy)//x距离大于y距离,那么每个x轴上只有一个点,每个y轴上有若干个点{//且线的点数等于x距离,以x轴递增画点// initialize error termerror = dy2 - dx; // draw the linefor (index=0; index <= dx; index++)//要画的点数不会超过x距离{//画点Gui_DrawPoint(x0,y0,Color);// test if error has overflowedif (error >= 0) //是否需要增加y坐标值{error-=dx2;// move to next liney0+=y_inc;//增加y坐标值} // end if error overflowed// adjust the error termerror+=dy2;// move to the next pixelx0+=x_inc;//x坐标值每次画点后都递增1} // end for} // end if |slope| <= 1else//y轴大于x轴,则每个y轴上只有一个点,x轴若干个点{//以y轴为递增画点// initialize error termerror = dx2 - dy; // draw the linefor (index=0; index <= dy; index++){// set the pixelGui_DrawPoint(x0,y0,Color);// test if error overflowedif (error >= 0){error-=dy2;// move to next linex0+=x_inc;} // end if error overflowed// adjust the error termerror+=dx2;// move to the next pixely0+=y_inc;} // end for} // end else |slope| > 1
}void Gui_box(u16 x, u16 y, u16 w, u16 h,u16 bc)
{Gui_DrawLine(x,y,x+w,y,0xEF7D);Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0x2965);Gui_DrawLine(x,y+h,x+w,y+h,0x2965);Gui_DrawLine(x,y,x,y+h,0xEF7D);Gui_DrawLine(x+1,y+1,x+1+w-2,y+1+h-2,bc);
}
void Gui_box2(u16 x,u16 y,u16 w,u16 h, u8 mode)
{if (mode==0) {Gui_DrawLine(x,y,x+w,y,0xEF7D);Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0x2965);Gui_DrawLine(x,y+h,x+w,y+h,0x2965);Gui_DrawLine(x,y,x,y+h,0xEF7D);}if (mode==1) {Gui_DrawLine(x,y,x+w,y,0x2965);Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0xEF7D);Gui_DrawLine(x,y+h,x+w,y+h,0xEF7D);Gui_DrawLine(x,y,x,y+h,0x2965);}if (mode==2) {Gui_DrawLine(x,y,x+w,y,0xffff);Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0xffff);Gui_DrawLine(x,y+h,x+w,y+h,0xffff);Gui_DrawLine(x,y,x,y+h,0xffff);}
}/**************************************************************************************
功能描述: 在屏幕显示一凸起的按钮框
输 入: u16 x1,y1,x2,y2 按钮框左上角和右下角坐标
输 出: 无
**************************************************************************************/
void DisplayButtonDown(u16 x1,u16 y1,u16 x2,u16 y2)
{Gui_DrawLine(x1, y1, x2,y1, GRAY2); //HGui_DrawLine(x1+1,y1+1,x2,y1+1, GRAY1); //HGui_DrawLine(x1, y1, x1,y2, GRAY2); //VGui_DrawLine(x1+1,y1+1,x1+1,y2, GRAY1); //VGui_DrawLine(x1, y2, x2,y2, WHITE); //HGui_DrawLine(x2, y1, x2,y2, WHITE); //V
}/**************************************************************************************
功能描述: 在屏幕显示一凹下的按钮框
输 入: u16 x1,y1,x2,y2 按钮框左上角和右下角坐标
输 出: 无
**************************************************************************************/
void DisplayButtonUp(u16 x1,u16 y1,u16 x2,u16 y2)
{Gui_DrawLine(x1, y1, x2,y1, WHITE); //HGui_DrawLine(x1, y1, x1,y2, WHITE); //VGui_DrawLine(x1+1,y2-1,x2,y2-1, GRAY1); //HGui_DrawLine(x1, y2, x2,y2, GRAY2); //HGui_DrawLine(x2-1,y1+1,x2-1,y2, GRAY1); //VGui_DrawLine(x2 ,y1 ,x2,y2, GRAY2); //V
}//display 16 ziti
void Gui_DrawFont_GBK16(u16 x, u16 y, u16 fc, u16 bc, u8 *s)
{unsigned char i,j;unsigned short k,x0;x0=x;while(*s) { if((*s) < 128) {k=*s;if (k==13) {x=x0;y+=16;}else {if (k>32) k-=32; else k=0;for(i=0;i<16;i++)for(j=0;j<8;j++) {if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);}}x+=8;}s++;}else {for (k=0;k<hz16_num;k++) {if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1))){ for(i=0;i<16;i++){for(j=0;j<8;j++) {if(hz16[k].Msk[i*2]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);}}for(j=0;j<8;j++) {if(hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint(x+j+8,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);}}}}}s+=2;x+=16;} }
}
//display 24 ziti
void Gui_DrawFont_GBK24(u16 x, u16 y, u16 fc, u16 bc, u8 *s)
{unsigned char i,j;unsigned short k;while(*s) {if( *s < 0x80 ) {k=*s;if (k>32) k-=32; else k=0;for(i=0;i<16;i++)for(j=0;j<8;j++) {if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);}}s++;x+=8;}else {for (k=0;k<hz24_num;k++) {if ((hz24[k].Index[0]==*(s))&&(hz24[k].Index[1]==*(s+1))){ for(i=0;i<24;i++){for(j=0;j<8;j++) {if(hz24[k].Msk[i*3]&(0x80>>j))Gui_DrawPoint(x+j,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);}}for(j=0;j<8;j++) {if(hz24[k].Msk[i*3+1]&(0x80>>j)) Gui_DrawPoint(x+j+8,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);}}for(j=0;j<8;j++) {if(hz24[k].Msk[i*3+2]&(0x80>>j)) Gui_DrawPoint(x+j+16,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j+16,y+i,bc);}}}}}s+=2;x+=24;}}
}void Gui_DrawFont_Num32(u16 x, u16 y, u16 fc, u16 bc, u16 num)
{unsigned char i,j,k,c;//lcd_text_any(x+94+i*42,y+34,32,32,0x7E8,0x0,sz32,knum[i]);
// w=w/8;for(i=0;i<32;i++){for(j=0;j<4;j++) {c=*(sz32+num*32*4+i*4+j);for (k=0;k<8;k++) {if(c&(0x80>>k)) Gui_DrawPoint(x+j*8+k,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j*8+k,y+i,bc);}}}}
}void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{ Lcd_WriteIndex(0x2a);Lcd_WriteData(x1>>8);Lcd_WriteData(x1);Lcd_WriteData(x2>>8);Lcd_WriteData(x2);Lcd_WriteIndex(0x2b);Lcd_WriteData(y1>>8);Lcd_WriteData(y1);Lcd_WriteData(y2>>8);Lcd_WriteData(y2);Lcd_WriteIndex(0x2C);
}//??
//POINT_COLOR:?????
void LCD_DrawPoint(u16 x,u16 y)
{Address_set(x,y,x,y);//?????? Lcd_WriteData_16Bit(POINT_COLOR);
} void LCD_ShowChar(u16 x,u16 y,u8 num,u8 mode)
{u8 temp;u8 pos,t;u16 x0=x;u16 colortemp=GREEN; if(x>LCD_X_SIZE-16||y>LCD_Y_SIZE-16)return; //???? num=num-' ';//???????Address_set(x,y,x+8-1,y+16-1); //??????if(mode) //?????{for(pos=0;pos<16;pos++){ temp=asc2_1608[(u16)num*16+pos]; //??1608??for(t=0;t<8;t++){ if(temp&0x01)POINT_COLOR=colortemp;else POINT_COLOR=BLACK;Lcd_WriteData_16Bit(POINT_COLOR); temp>>=1; x++;}x=x0;y++;} }else//????{for(pos=0;pos<16;pos++){temp=asc2_1608[(u16)num*16+pos]; //??1608??for(t=0;t<8;t++){ if(temp&0x01)LCD_DrawPoint(x+t,y+pos);//???? temp>>=1; }}}POINT_COLOR=colortemp;
} unsigned long oled_pow(u8 m,u8 n)
{unsigned long result=1; while(n--)result*=m; return result;
}void LCD_Showdecimal(u8 x,u8 y,float num,u8 z_len,u8 f_len,u8 size2)
{ u8 t,temp;u8 enshow;int z_temp,f_temp; z_temp=(int)num;//????for(t=0;t<z_len;t++){temp=(z_temp/oled_pow(10,z_len-t-1))%10;if(enshow==0 && t<(z_len-1)){if(temp==0){LCD_ShowChar(x+(size2/2)*t,y,' ',size2);continue;}elseenshow=1;}LCD_ShowChar(x+(size2/2)*t,y,temp+'0',size2); }//???LCD_ShowChar(x+(size2/2)*(z_len),y,'.',size2); f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));//????for(t=0;t<f_len;t++){temp=(f_temp/oled_pow(10,f_len-t-1))%10;LCD_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2); }
}void showhanzi(unsigned int x,unsigned int y,unsigned char index)
{ unsigned char i,j;unsigned char *temp=hanzi; Address_set(x,y,x+31,y+31); //设置区域 temp+=index*128; for(j=0;j<128;j++){for(i=0;i<8;i++){ if((*temp&(1<<i))!=0){Lcd_WriteData_16Bit(POINT_COLOR);} else{Lcd_WriteData_16Bit(WHITE);} }temp++;}
}//显示图片
void showimage(const unsigned char *p)
{//??128*128 ??int i; unsigned char picH,picL;
// Lcd_Clear(WHITE); //?? ->1 Address_set(100,100,219,219);for(i=0;i<120*120;i++){ picL=*(p+i*2); //??????picH=*(p+i*2+1); Lcd_WriteData_16Bit(picH<<8|picL); }
}//??2???
//x,y :????
//len :?????
//color:??
//num:??(0~4294967295);
void LCD_ShowNum(u16 x,u16 y,unsigned long num,u8 len)
{ u8 t,temp;u8 enshow=0;num=(u16)num;for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1))%10;if(enshow==0&&t<(len-1)){if(temp==0){LCD_ShowChar(x+8*t,y,' ',1);continue;}else enshow=1; }LCD_ShowChar(x+8*t,y,temp+48,1); }
} void picture()
{showimage(gImage_new);
}//矩形
void rectangle(u16 x0, u16 y0, u16 x1, u16 y1,u16 bc)
{int i,j;for(i=x0;i<=x1;i++){for(j=y0;j<=y1;j++){Gui_DrawPoint(i,j,bc);}}
}void LCD_DrawPoint2(u16 x,u16 y,u16 Color)
{Address_set(x,y,x,y);//?????? Lcd_WriteData_16Bit(Color);
}
(5)radar.c 雷达图的绘制
#include "radar.h"
#include "LCDAPI.h"
#include "lcd.h"
#include "math.h"
#include "hc-sr04.h"void Radarline(double k,int r)
{double x,y;x=160+r*(double)cos(k/180*3.1415926); y=200-r*(double)sin(k/180*3.1415926);Gui_DrawLine(160,200,x,y,GREEN);}void radar_picture()
{Gui_DrawFont_GBK24(307,98,GREEN,BLACK,"°");Gui_DrawFont_GBK24(263,58,GREEN,BLACK,"°");Gui_DrawFont_GBK24(181,28,GREEN,BLACK,"°");Gui_DrawFont_GBK24(110,40,GREEN,BLACK,"°");Gui_DrawFont_GBK24(35,90,GREEN,BLACK,"°");//雷达图Gui_Circle(160,200,152,GREEN);Gui_Circle(160,200,114,GREEN);Gui_Circle(160,200,76,GREEN);Gui_Circle(160,200,38,GREEN);Radarline(30,170);Radarline(60,170);Radarline(90,170);Radarline(120,170);Radarline(150,170);rectangle(0,200,320,240,BLACK);Gui_DrawLine(0,200,320,200,GREEN);//数据信息Gui_DrawFont_GBK24(0,212,GREEN,BLACK,"距离");Gui_DrawFont_GBK24(50,219,GREEN,BLACK,":");Gui_DrawFont_GBK24(0,0,GREEN,BLACK,"角度");Gui_DrawFont_GBK24(50,7,GREEN,BLACK,":");Gui_DrawFont_GBK24(117,211,GREEN,BLACK,"CM"); Gui_DrawFont_GBK24(100,0,GREEN,BLACK,"°");Gui_DrawFont_GBK16(175,205,GREEN,BLACK,"25");Gui_DrawFont_GBK16(210,205,GREEN,BLACK,"50");Gui_DrawFont_GBK16(245,205,GREEN,BLACK,"75");Gui_DrawFont_GBK16(285,205,GREEN,BLACK,"100");Gui_DrawFont_GBK16(290,100,GREEN,BLACK,"30");Gui_DrawFont_GBK16(247,60,GREEN,BLACK,"60");Gui_DrawFont_GBK16(165,30,GREEN,BLACK,"90");Gui_DrawFont_GBK16(85,42,GREEN,BLACK,"120");Gui_DrawFont_GBK16(10,92,GREEN,BLACK,"150");Gui_DrawFont_GBK24(190,0,GREEN,BLACK,"超声波雷达");// Gui_DrawFont_GBK24(307,98,GREEN,BLACK,"°");
// Gui_DrawFont_GBK24(263,58,GREEN,BLACK,"°");
// Gui_DrawFont_GBK24(185,28,GREEN,BLACK,"°");
// Gui_DrawFont_GBK24(110,40,GREEN,BLACK,"°");
// Gui_DrawFont_GBK24(35,90,GREEN,BLACK,"°");
}
七、程序源码工程及原理图下载链接
https://download.csdn.net/download/jacklood/91023554