STM32红外循迹智能车,TFT液晶显示

STM32红外循迹智能车,TFT液晶显示

STM32红外循迹小车是一种基于STM32微控制器的嵌入式系统项目,它利用红外传感器来检测特定颜色(通常是黑色)的路径,并沿着这条路径自动移动。以下是对STM32红外循迹小车的详细介绍:

 一、核心硬件

1. STM32微控制器:常用的型号是STM32F103C8T6,这是一款基于Cortex-M3内核的32位微控制器,具有丰富的外设接口和强大的处理能力。

2. 红外循迹传感器模块:

使用TCRT5000传感器,它包含一个红外发射二极管和一个红外接收管。这些传感器连接到STM32的GPIO输入引脚,用于检测路径的颜色。

3. 电机驱动模块:

电机驱动模块是L298N,它连接到STM32的PWM输出引脚,用于控制电机的速度和方向。

L298驱动产品简介:

电机驱动模块供电电压2V~10V,可同时驱动两个直流电机或者1个4线2相式步进电机,可实现正反转和调速的功能,每路电流能到1.5A持续电流,峰值电流可达2.5A,有热保护并且能够自动恢复。

产品亮点:

1. 采用进口原装专业电机驱动芯片,内置低导通内阻MOS开关管,发热极小,无需散热片,体积小,省电,是您电池供电的理想选择

2. 双路1.5A*2,峰值电流可到2.5A, 内置过热保护电路,不用怕电机堵转烧坏,温度下降后自动恢复。(目前市面上的智能小车电压和电流都在此范围内)

3. 体积小,质量轻,0待机电流,是您模型车载的理想选择

4. 直流电机:作为小车的动力源,连接到L298N电机驱动模块。

直流电机驱动逻辑真值表:

INx接单片机IO或者其他信号源,MOTOR-A和MOTOR-B端接电机

https://img.alicdn.com/imgextra/i2/1712400798/TB2kl3orVXXXXblXXXXXXXXXXXX_!!1712400798.jpg

产品参数:

1.双路H桥电机驱动,可以同时驱动两路直流电机或者1个4线两相式步进电机;

2.模块供电电压2V-10V;

3.信号端输入电压1.8-7V;

4.单路工作电流1.5A,峰值电流可达2.5A,低待机电流 (小于 0.1uA);

5.内置防共态导通电路,输入端悬空时,电机不会误动作;

6.内置带迟滞效应的过热保护电路 (TSD),无需担心电机堵转;

TFT-LCD模块简介

        TFT-LCD(Thin Film Transistor)液晶显示屏是薄膜晶体管型液晶显示屏,也就是“真彩”(TFT)。TFT液晶为每个像素都设有一个半导体开关,每个像素都可以通过点脉冲直接控制,因而每个节点都相对独立,并可以连续控制,不仅提高了显示屏的反应速度,同时可以精确控制显示色阶,所以TFT液晶的色彩更真。TFT液晶显示屏的特点是亮度好、对比度高、层次感强、颜色鲜艳,但也存在着比较耗电和成本过高的不足。

硬件连接

以STM32F103C8T6和2.4寸TFT-LCD(240×320)为例,硬件连接如下:

  • VCC --> 3.3V
  • GND --> GND
  • CS --> PB11
  • Reset --> PB12
  • DC --> PB10
  • SDI --> PB15
  • SCK --> PB13
  • LED --> PB9(控制LCD背光,可通过PWM调节亮度)

SPI通讯

TFT-LCD模块通常使用SPI协议进行通讯。SPI协议是一种高速全双工的通信总线,使用3条总线(SCK、MOSI、MISO)及片选线(SS/CS)1

初始化代码

以下是TFT-LCD的初始化代码示例:

void Lcd_Init(void) {

Lcd_Reset(); // Reset before LCD Init

Lcd_WriteIndex(0x11);

Lcd_WriteData(0x00);

Lcd_WriteIndex(0xCF);

Lcd_WriteData(0X00);

Lcd_WriteData(0XC1);

Lcd_WriteData(0X30);

// 省略部分初始化代码

Lcd_WriteIndex(0x29);

}

该代码初始化了TFT-LCD的各个寄存器,确保屏幕能够正常显示1

显示函数

TFT-LCD的显示需要依赖几个基础功能函数,如设置显示区域、画点、清屏等:

void Lcd_SetXY(u16 Xpos, u16 Ypos) {

Lcd_WriteIndex(0x2A);

Lcd_WriteData_16Bit(Xpos);

Lcd_WriteIndex(0x2B);

Lcd_WriteData_16Bit(Ypos);

Lcd_WriteIndex(0x2c);

}

void Gui_DrawPoint(u16 x, u16 y, u16 Data) {

Lcd_SetXY(x, y);

Lcd_WriteData_16Bit(Data);

}

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++) {

SPIv_WriteData(Color >> 8);

SPIv_WriteData(Color);

}

LCD_CS_SET;

}

这些函数用于设置显示区域、绘制点和清屏1

二、硬件连接

1. STM32与红外循迹传感器的连接:将红外循迹传感器的输出引脚连接到STM32的GPIO输入引脚,以便读取传感器的状态。

2. STM32与电机驱动模块的连接:将STM32的PWM输出引脚连接到电机驱动模块的输入引脚,用于控制电机的速度和方向。同时,将电机的电源线和地线分别连接到电机驱动模块的电源输入端和地线端。

三、软件编程

1. 初始化配置:

    * 配置GPIO引脚为输入模式或输出模式,以连接红外循迹传感器和电机驱动模块。

    * 启用外部中断(如果需要使用)。

    * 配置定时器以产生PWM信号,控制电机的速度。

2. 循迹逻辑:

    * 根据红外传感器的输入,判断小车当前所在的位置。

    * 根据位置信息,控制电机的转向和速度,使小车沿着黑线移动。

    * 常用的控制策略包括:当检测到黑线在中间时,小车直行;当检测到黑线在左侧时,小车右转;当检测到黑线在右侧时,小车左转;当未检测到黑线时,小车停车。

3. 主循环:在主函数中,初始化硬件后进入循环,不断检测传感器状态并调整小车方向。

四、注意事项

1. 传感器校准:确保红外传感器正确校准,以准确检测黑线。

2. 电源稳定性:确保电源稳定,避免电压波动影响传感器和电机的稳定性。

3. 代码优化:根据实际应用需求,优化循迹算法和PWM控制逻辑。

代码

#include "delay.h"

#include "sys.h"

#include "lcd.h"

#include "touch.h"

#include "gui.h"

#include "test.h"

#include "stm32f10x.h"

#define ON  0

#define OFF 1

//STM32F103

//   

/****************************************************************************************************

//=======================================液晶屏数据线接线==========================================//

//CS       接PB12 //片选信号

//CLK      接PB13    //SPI时钟信号

//SDI(DIN) 接PB15 //SPI总线数据信号

//=======================================液晶屏控制线接线==========================================//

//RS(D/C)   接PB1    //寄存器/数据选择信号(RS=0数据总线发送的是指令;RS=1数据总线发送的是像素数据)

/

//==================================如何精简到只需要3个IO=======================================//

//1.CS信号可以精简,不作SPI复用片选可将CS接地常低,节省1个IO

//2.LED背光控制信号可以接高电平3.3V背光常亮,节省1个IO

//3.RST复位信号可以接到单片机的复位端,利用系统上电复位,节省1个IO

//==================================如何切换横竖屏显示=======================================//

//打开lcd.h头文件,修改宏#define USE_HORIZONTAL 值为0使用竖屏模式.1,使用横屏模式

//===========================如何切换模拟SPI总线驱动和硬件SPI总线驱动=========================//

//打开lcd.h头文件,修改宏#define USE_HARDWARE_SPI  值为0使用模拟SPI总线.1,使用硬件SPI总线

**************************************************************************************************/   

u16 LeftEye = 0; 

u16 RightEye = 0;

 /***************  小车配置用到的I/O口 *******************/

void GPIO_Config(void)  

{

    /**************电机驱动管教*******************/

    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); // 使能PA端口时钟 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择电机A1对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA端口

    GPIO_SetBits(GPIOA, GPIO_Pin_0 );  // 电机A1

   

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //选择电机A2对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA端口

    GPIO_SetBits(GPIOA, GPIO_Pin_1 );  // 电机A2

   

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //选择电机B1对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA端口

    GPIO_SetBits(GPIOA, GPIO_Pin_2 );  // 电机B1

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //选择电机B2对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA端口

    GPIO_SetBits(GPIOA, GPIO_Pin_3 );  // 电机B2

    /**************红外循迹*******************/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //选择红外循迹左边对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA端口

    GPIO_SetBits(GPIOA, GPIO_Pin_5 ); 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //选择红外循迹右边对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA端口

    GPIO_SetBits(GPIOA, GPIO_Pin_6 );

   

    /**************LED*******************/

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); // 使能PC端口时钟 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;    //选择LED灯对应的引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);  //初始化PC端口

    GPIO_SetBits(GPIOC, GPIO_Pin_13 ); // 关闭所有LED

}

void XunjiCheck(void)//红外循迹传感器查询

{

     LeftEye = (GPIO_ReadInputData(GPIOA)&0x20)>>5;

     RightEye = (GPIO_ReadInputData(GPIOA)&0x40)>>6;

}

void MotorStop(void)    //小车停止

{

    GPIO_ResetBits(GPIOA,GPIO_Pin_0);

    GPIO_ResetBits(GPIOA,GPIO_Pin_1);

    GPIO_ResetBits(GPIOA,GPIO_Pin_2);

    GPIO_ResetBits(GPIOA,GPIO_Pin_3);

}

void MotorRun(void)     //小车启动

{

    GPIO_SetBits(GPIOA,GPIO_Pin_0);

    GPIO_ResetBits(GPIOA,GPIO_Pin_1);

    GPIO_SetBits(GPIOA,GPIO_Pin_2);

    GPIO_ResetBits(GPIOA,GPIO_Pin_3);

}

void MotorTurnLeft(void)    //小车左转

{

    GPIO_ResetBits(GPIOA,GPIO_Pin_0);

    GPIO_ResetBits(GPIOA,GPIO_Pin_1);

    GPIO_SetBits(GPIOA,GPIO_Pin_2);

    GPIO_ResetBits(GPIOA,GPIO_Pin_3);

}

void MotorTurnRight(void)      //小车右转

{  

    GPIO_SetBits(GPIOA,GPIO_Pin_0);

    GPIO_ResetBits(GPIOA,GPIO_Pin_1);

    GPIO_ResetBits(GPIOA,GPIO_Pin_2);

    GPIO_ResetBits(GPIOA,GPIO_Pin_3);

}

void LED1(char led)     //LED灯

{

    if(led==1)

    {

       GPIO_SetBits(GPIOC,GPIO_Pin_13);  

    }

    else  

    {

       GPIO_ResetBits(GPIOC,GPIO_Pin_13);

    }

}

void Delay(u32 nCount)

{

  for(; nCount != 0; nCount--);

}

int main(void)

{  

    SystemInit();//初始化RCC 设置系统主频为72MHZ

    delay_init(72);        //延时初始化

    LCD_Init();      //液晶屏初始化

    LCD_Clear(BLACK); //清屏

    POINT_COLOR=WHITE;

   

    LCD_DrawRectangle(0,0,128-1,128-1);    //画矩形

    Show_Str(32,5,BLUE,YELLOW,"系统监控",16,0);

   

    Show_Str(5,25,RED,YELLOW,"温度     ℃",24,1);

   

    LCD_ShowNum2412(5+48,25,RED,YELLOW,":32",24,1);

    Show_Str(5,50,YELLOW,YELLOW,"湿度     %",24,1);

    LCD_ShowNum2412(5+48,50,YELLOW,YELLOW,":20",24,1);

    Show_Str(5,75,WHITE,YELLOW,"电压      V",24,1);

    LCD_ShowNum2412(5+48,75,WHITE,YELLOW,":3.2",24,1);

    Show_Str(5,100,GREEN,YELLOW,"电流      A",24,1);

    LCD_ShowNum2412(5+48,100,GREEN,YELLOW,":0.2",24,1);   

 

    /*小车初始化*/

    GPIO_Config();

    while(1)

    {  

       //LED1( ON );          // 亮

       //Delay(0x200000);

       //LED1( OFF );         // 灭

       //Delay(0x200000);

       //MotorRun();

       XunjiCheck();

       if((LeftEye == 0)&&(RightEye == 0))           //看到白色为0,看到黑色为1

           {

              MotorRun();

           }

           else if((LeftEye == 1)&&(RightEye == 0))  //左边看到黑线

           {

              MotorTurnRight();

              Delay(20);       

           }

           else if((RightEye == 1)&&(LeftEye == 0))

           {

              MotorTurnLeft(); 

              Delay(20);

           }

           else

           {

              MotorStop();

           }  

                                                                                                                                             

    };

              

}

51单片机利用四路红外循迹模块循双黑线的逻辑如下: 1. 初始化引脚:将红外循迹模块的输出引脚连接到P1口的0-3号引脚,电机的控制引脚连接到P2口的0-3号引脚。 2. 进入循迹循环:在一个无限循环中,不断检测红外传感器的状态并根据状态来控制车辆的动作。 3. 判断传感器状态:通过检测四个红外传感器的输出状态,判断当前车辆所处的位置。根据双黑线循迹的逻辑,有以下几种情况: - 左传感器1和右传感器2都检测到黑线,表示车辆在直线上,向前行驶; - 左传感器2和右传感器1都检测到黑线,表示车辆在直线上,向前行驶; - 只有左传感器2检测到黑线,表示车辆偏离了右侧黑线,需要向左转; - 只有右传感器2检测到黑线,表示车辆偏离了左侧黑线,需要向右转; - 其他情况下,车辆停止。 4. 执行动作:根据传感器状态判断的结果,执行相应的动作控制函数,使车辆进行直行、左转、右转或停止操作。 5. 循迹延时:在每次执行动作后,可以添加一段延时,使车辆在执行动作后有一定的停顿时间,避免动作过于频繁。 6. 循迹循环:回到循迹循环的开始,继续检测传感器状态和执行相应的动作,以保持车辆在双黑线上循迹行驶。 根据具体的红外传感器和电机的连接方式,你可能需要调整引脚定义和判断逻辑。以上逻辑是一个简单的示例,可以根据你的实际需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大道至简研究室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值