找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3957|回复: 3
收起左侧

基于STM32单片机红外遥控智能小车程序

[复制链接]
ID:475371 发表于 2020-6-8 15:32 | 显示全部楼层 |阅读模式
本帖最后由 flytohign 于 2020-6-9 10:23 编辑

本项目采用STM32单片机和L298电机驱动模块,简单连线制作;后期会加入避障和循迹功能;/************************************************
开发板:STM32F10x+L298N直流电机驱动器
项目名称:基于STM32红外遥控智能小车设计
功能:1.红外遥控小车前进、后退,左转弯、右转弯
2.小车前进后退0-10档加减速、指定档位变速
端口定义:IN1--GPIOC_pin0
IN2--GPIOC_pin1
IN3--GPIOC_pin2
IN4--GPIOC_pin3
ENA--GPIOF_pin0
ENB--GPIOF_pin1
STM32电源---VCC 3.3V
电源配置:直流电机驱动L298电源--VCC 6.0V
特别注意:电机驱动和单片机分别供电,要特别主要STM32单片机和L298N共地连接
                这个我开始没注意,花费了不少时间
日期:2020年6月4日,第一次
************************************************/
1.硬件选型
L298使用说明_爱奇艺.jpg
由于程序设计过程中涉及第三方代码,我贴出我自己设计的主要函数,应该很容易能够搭建项目的;
主要设计函数就是我定义的motorcon.h和motorcon.c文件,包括一些红外小车的前进、后退、左转和右转,暂停等;
在中断函数exti.c和exti.h中完成红外遥控信号的识别,并数据处理;
捕获.PNG
2.源程序
主函数
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "lcd.h"
  6. #include "usart.h"     
  7. #include "remote.h"
  8. #include "motorcon.h"
  9. #include "exti.h"
  10. #include "beep.h"
  11. /************************************************
  12. 开发板:STM32F10x+L298N直流电机驱动器
  13. 项目名称:基于STM32红外遥控智能小车设计  
  14. <font color="#ff0000">功能:1.红外遥控小车前进、后退,左转弯、右转弯
  15.        2.小车前进后退0-10档加减速、指定档位变速</font>
  16. 端口定义:IN1--GPIOC_pin0
  17.            IN2--GPIOC_pin1
  18.                      IN3--GPIOC_pin2
  19.                      IN4--GPIOC_pin3
  20.                      ENA--GPIOF_pin0
  21.                      ENB--GPIOF_pin1
  22.                      STM32电源---VCC 3.3V
  23.     电源配置:直流电机驱动L298电源--VCC 6.0V
  24.      特别注意:STM32单片机和L298N共地连接
  25. 日期:2020年6月4日,第一次
  26. ************************************************/

  27. int main(void)
  28. {     
  29.       
  30.     delay_init();             //延时函数初始化      
  31.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  32.     uart_init(115200);         //串口初始化为115200
  33.      LED_Init();                 //LED端口初始化
  34.     LCD_Init();   
  35.     KEY_Init();         
  36.     Remote_Init();            //红外接收初始化            
  37.   Motor_IOconfig();  //电机端口初始化
  38.     BEEP_Init();             //初始化蜂鸣器IO
  39.     EXTIX_Init();             //初始化外部中断输入
  40.      
  41.      POINT_COLOR=RED;        //设置字体为红色
  42.     LCD_ShowString(30,50,200,16,16,"STM32+L289N");
  43.     LCD_ShowString(30,70,200,16,16,"REMOTE INTELLIGENCE CAR");   
  44.     LCD_ShowString(30,90,200,16,16,"PARAMETER DISPLAY");
  45.     LCD_ShowString(30,110,200,16,16,"2020/6/4");

  46.        LCD_ShowString(30,130,200,16,16,"KEYVALA:");   
  47.        LCD_ShowString(30,150,200,16,16,"KEYCONT:");   
  48.        LCD_ShowString(30,170,200,16,16,"SYMBOLY:");     
  49.     LCD_ShowString(30,190,200,16,16,"SPEED LEVEL:");            
  50.     while(1)
  51.     {
  52.             
  53.             if(flagforward==1)
  54.             {motor_Sforward();}
  55.             if(flagback==1)
  56.             {motor_Sback();}
  57. //            if(flagleft==1)
  58. //            {motor_left();}
  59. //            if(flagright==1)
  60. //            {motor_right();}
  61. //            if(flagstop==1)
  62. //            {motor_stop();}   
  63.     }
  64. }
复制代码


头文件exti.h
定义了外部变量flagforward,flagback和num,di_num,gao_num
  1. #ifndef __EXTI_H
  2. #define __EXIT_H     
  3. #include "sys.h"
  4.         
  5. void EXTIX_Init(void);//外部中断初始化   

  6. extern u8 flagforward,flagback;//flagleft,flagright,flagstop;
  7. extern u8 num,di_num,gao_num;
  8. #endif
复制代码


源程序exti.c
中断程序,采用重映射功能将红外接收端口映射到中断线;这一步很重要;
然后根据中断函数的红外接收号,执行相应功能;
这里特别注意前进和后退的中断识别设计,采用flagforward,flagback标志位来标记前进和后退指令;
这一步想了好久,不这样的话前进和后退 小车没反应;
  1. #include "exti.h"
  2. #include "led.h"
  3. #include "key.h"
  4. #include "delay.h"
  5. #include "usart.h"
  6. #include "beep.h"
  7. #include "remote.h"
  8. #include "lcd.h"
  9. #include "motorcon.h"

  10. //外部中断0服务程序,0-15位IO中断

  11. void EXTIX_Init(void)
  12. {

  13.        EXTI_InitTypeDef EXTI_InitStructure;
  14.        NVIC_InitTypeDef NVIC_InitStructure;

  15.       RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);    //使能复用功能时钟

  16.    //GPIOB.9      中断线以及中断初始化配置 下降沿触发 //REMOTE IN
  17.       GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);//GPIO与中断线的映射关系
  18.       EXTI_InitStructure.EXTI_Line=EXTI_Line9;    //中断线9,取值范围为0-15
  19.       EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;    //中断模式
  20.       EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发中断
  21.       EXTI_Init(&EXTI_InitStructure);     

  22.    //NVIC中断优先级设置
  23.       NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;            //使能红外接收二极管所对应的外部中断通道
  24.       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;    //抢占优先级2,
  25.       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;                    //子优先级0
  26.       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                //使能外部中断通道
  27.       NVIC_Init(&NVIC_InitStructure);

  28.   

  29. }
  30. u8 key;
  31. u8 flagforward=0,flagback=0;//flagleft=0,flagright=0,flagstop=0;
  32. u8 num=0,di_num=10,gao_num=0;
  33. //外部中断9服务程序 ,中断线5-9
  34. void EXTI9_5_IRQHandler(void)
  35. {
  36.    
  37.     if(EXTI_GetITStatus(EXTI_Line9)!=RESET) //判断某个中断线是否有中断产生
  38.     {
  39.       u8 *str=0;           //***定义字符换指针str**//
  40.         key=Remote_Scan();   //接收红外发送数值
  41.         if(key)
  42.         {     
  43.             LCD_ShowNum(86,130,key,3,16);        //显示键值
  44.             LCD_ShowNum(86,150,RmtCnt,3,16);    //显示按键次数         
  45.             switch(key)
  46.             {
  47.                 case 0:str="ERROR";break;               
  48.                 case 162:str="POWER";    //停车
  49.                        //  flagstop=1;
  50.                 motor_stop();
  51.                          break;        
  52.                 case 98:str="UP";  
  53.                 flagforward=1,flagback=0;  //前进
  54.                         break;        
  55.                 case 2:str="PLAY";break;         
  56.                 case 226:str="ALIENTEK";break;         
  57.                 case 194:str="RIGHT";  //右转
  58.                       //   flagright=1,flagleft=0;
  59.                motor_right();               
  60.                 break;      
  61.                 case 34:str="LEFT";   //左转
  62.                       //  flagleft=1,flagright=0;  
  63.                 motor_left();               
  64.                         break;         
  65.                 case 224:str="VOL-";  //减速
  66.                          if(num!=0)
  67.                                      num--;
  68.                                  else
  69.                                      num=0;
  70.                                  motor_reddisp();
  71.                          break;         
  72.                 case 168:str="DOWN";    //后退
  73.                                  flagback=1,flagforward=0;
  74.                                  break;           
  75.                 case 144:str="VOL+";  //加速
  76.                                  num++;
  77.                                  if(num==10)
  78.                                      num=10;
  79.                                  motor_reddisp();
  80.                                  break;        
  81.                                  
  82.                 case 104:str="1";num=0;gao_num=0;di_num=10;break;         //指定档位
  83.                 case 152:str="2";num=1;gao_num=1;di_num=9;break;      
  84.                 case 176:str="3";num=2;gao_num=2;di_num=8;break;        
  85.                 case 48:str="4";num=3;gao_num=3;di_num=7;break;            
  86.                 case 24:str="5";num=4;gao_num=4;di_num=6;break;            
  87.                 case 122:str="6";num=5;gao_num=5;di_num=5;break;         
  88.                 case 16:str="7";num=6;gao_num=6;di_num=4;break;                                   
  89.                 case 56:str="8";num=7;gao_num=7;di_num=3;break;     
  90.                 case 90:str="9";num=8;gao_num=8;di_num=2;break;
  91.                 case 66:str="0";num=9;gao_num=9;di_num=1;break;
  92.                 case 82:str="DELETE";num=10;gao_num=10;di_num=0;break;         
  93.             }
  94.             LCD_Fill(86,170,116+8*8,170+16,WHITE);    //清楚之前的显示
  95.             LCD_ShowString(86,170,200,16,16,str);    //显示SYMBOLY
  96.             LCD_ShowNum(86,190,num,3,16);    //显示按键次数   
  97.             
  98.         }
  99.         BEEP=!BEEP;   
  100.         EXTI_ClearITPendingBit(EXTI_Line9); //清除LINE0上的中断标志位  
  101.     }
  102.    
  103. }
复制代码


源文件motorcon.h
定义了一些端口;
还有电机控制函数;
  1. #ifndef _MOTORCON_H
  2. #define _MOTORCON_H
  3. #include "sys.h"

  4. #define uint unsigned int
  5. #define uchar unsigned char

  6. #define IN1 PCout(0)
  7. #define IN2 PCout(1)
  8. #define IN3 PCout(2)
  9. #define IN4 PCout(3)
  10. #define ENA PFout(0)
  11. #define ENB PFout(1)

  12. void Motor_IOconfig(void);   
  13. void motor_Sforward(void);
  14. void motor_Sback(void);
  15. void motor_left(void);
  16. void motor_right(void);
  17. void motor_stop(void);
  18. void motor_redkchange(void);
  19. void motor_reddisp(void);

  20. #endif
复制代码


源程序motorcon.c
这一步为核心控制环节;
分别设计了前进和后退的PWM控制函数。实现小车 的前进后退的变速运行;
档位可能具体数值有问题,但是能基本实现变速调节;效果不错;
  1. #include "motorcon.h"
  2. extern u8 num,di_num,gao_num;
  3. void Motor_IOconfig()
  4. {
  5.      GPIO_InitTypeDef  GPIO_InitStructure;     
  6.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOF,ENABLE);     //使能GPIOC和GPIOF端口时钟
  7.             
  8.          GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;    //GPIOC端口配置
  9.          GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;          //推挽输出
  10.          GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;         //IO口速度为50MHz
  11.          GPIO_Init(GPIOC, &GPIO_InitStructure);               
  12.        GPIO_ResetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);   
  13.        //GPIO_C的0,1,2,3端口初始化为低电平,即IN1-IN4端口
  14.    
  15.        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1;//设置引脚模式为推免输出模式,,IO口速度为50MHz
  16.        GPIO_Init(GPIOF,&GPIO_InitStructure);
  17.        GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1);    //GPIO_F的0,1端口初始化为低电平,即ENA端口
  18. }

  19. /*电机前进函数*/
  20. void motor_Sforward()
  21. {
  22.     uchar i;
  23.       IN1=1;
  24.       IN2=0;
  25.    
  26.             for(i=0;i<di_num;i++)
  27.             {
  28.                 ENA=0; //PWM低电平输出
  29.             }         
  30.       for(i=0;i<gao_num;i++)
  31.             {
  32.                ENA=1; //PWM高电平输出
  33.             }
  34.         
  35. }

  36. /*电机后退函数*/
  37. void motor_Sback()
  38. {
  39.    uchar i;
  40.      IN1=0;
  41.      IN2=1;
  42.      for(i=0;i<di_num;i++)
  43.     {
  44.        ENA=0;
  45.     }
  46.     for(i=0;i<gao_num;i++)
  47.     {
  48.        ENA=1;
  49.     }
  50. }

  51. /*左转弯函数*/
  52. void motor_left()
  53. {
  54.      ENB=1;
  55.     IN3=0;
  56.     IN4=1;
  57.    
  58. }   
  59. /*右转弯函数*/
  60. void motor_right()
  61. {
  62.     ENB=1;
  63.     IN3=1;
  64.     IN4=0;
  65.    
  66. }
  67. /*电机停止函数*/
  68. void motor_stop()
  69. {
  70.     ENA=0;
  71.       ENB=0;
  72. }

  73. /*红外数据处理函数*/
  74. void motor_reddisp()
  75. {

  76.     switch(num)
  77.    {
  78.       case 0:
  79.              gao_num=0;      //高电平持续时间为1,低电平为3
  80.              di_num=10;
  81.              break;
  82.       case 1:
  83.              gao_num=1;     //高电平持续时间为8,低电平持续时间为2
  84.              di_num=9;
  85.              break;
  86.      case 2:
  87.             gao_num=2;    //高电平持续时间为7,低电平持续时间为3
  88.             di_num=8;
  89.             break;
  90.     case 3:
  91.            gao_num=3;  //高电平持续时间为6,低电平持续时间为4
  92.            di_num=7;
  93.            break;
  94.     case 4:
  95.            gao_num=4;  //高电平持续时间为5,低电平持续时间为5
  96.            di_num=6;
  97.            break;
  98.     case 5:
  99.            gao_num=5;  //高电平持续时间为4,低电平持续时间为0
  100.            di_num=5;
  101.            break;
  102.     case 6:
  103.            gao_num=6;  //高电平持续时间为6,低电平持续时间为4
  104.            di_num=4;
  105.            break;
  106.     case 7:
  107.            gao_num=7;  //高电平持续时间为7,低电平持续时间为3
  108.            di_num=3;
  109.            break;
  110.     case 8:
  111.            gao_num=8;  //高电平持续时间为8,低电平持续时间为2
  112.            di_num=2;
  113.            break;
  114.     case 9:
  115.            gao_num=9;  //高电平持续时间为9,低电平持续时间为1
  116.            di_num=1;
  117.            break;
  118.     case 10:
  119.            gao_num=10;  //高电平持续时间为10,低电平持续时间为0
  120.            di_num=0;
  121.            break;
  122.    }
  123. }
复制代码


硬件实物设计
实物很简单,通过一个L298驱动器驱动前后轮,前轮转向,后轮驱动前进后退;
在加入任一单片机控制器就可以制作了。要实现变档,估计单纯的51/52单片机很难实现。

51hei图片20200609095902.jpg 51hei图片20200609095852.jpg

复制代码









回复

使用道具 举报

ID:475371 发表于 2020-6-8 22:41 | 显示全部楼层
admin 发表于 2020-6-8 22:12
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)

好的,给我点时间哈,我尽量补全
回复

使用道具 举报

ID:249746 发表于 2020-6-30 21:45 | 显示全部楼层
有原理图和代码吗?正在搞这个,大家交流一下?
回复

使用道具 举报

ID:1053168 发表于 2022-11-21 16:35 | 显示全部楼层
朋友为什么按照你的代码做了,为什么#include "motorcon.h" 这个函数 旁边是红色的x啊??
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表