[其他ST产品] 基于STM32F103智能小车黑线寻迹运动实验(有代码)

[复制链接]
 楼主| 4c1l 发表于 2022-8-29 23:37 | 显示全部楼层 |阅读模式
小车设计

利用STM32作为智能小车的主控制器来驱动智能小车的直流电机工作,电机驱动芯片采用L298N微型集成电路电机驱动芯片,配合STM32核心板使用实现四个直流电机运行和pwm软件调速,通过改变直流电机占空比的电压来改变平均电压的数值,从而改变电机的转速变化来驱动轮式机器人运行。轮式机器人行驶的状态有:前进、后退、左转、右转和停止。当轮式机器人在行驶过程中遇到障碍物,红外避障检测模块检测周围障碍物,轮式机器人自动停止或转向。通过WIFI无线信号作为传输媒介,以上位机或手机作为控制端来控制机器人的运动以及将摄像头所拍摄的视频信息在控制端界面中显示,这样便可观察轮式机器人周围的环境并对机器人进行实时监控。


评论

———————————————— 版权声明:本文为CSDN博主「ShawnWang1994」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ShawnWang1994/article/details/111259569  发表于 2022-8-29 23:38
 楼主| 4c1l 发表于 2022-8-29 23:38 | 显示全部楼层
主要设计步骤有:

(1)根据提出方案的功能需求对智能小车进行结构设计。
 楼主| 4c1l 发表于 2022-8-29 23:39 | 显示全部楼层
(2)根据主控制器的基本结构和特点,设计总体硬件电路模块。总体硬件电路模块的设计包括电机驱动电路设计、红外避障电路设计、无线传输电路设计等。
 楼主| 4c1l 发表于 2022-8-29 23:41 | 显示全部楼层
(3)选择符合系统设计需求的系统软件,并在该软件的基础上编写驱动代码和应用软件代码。针对系统功能的具体要求,从系统信号稳定传输的角度出发,对电机驱动、调速、无线路由器系统的改造、视频信息的接受与发送、红外避障模块的改造和控制端界面的设计等进行详细的分析与设计,并完成代码的编写与调试。
 楼主| 4c1l 发表于 2022-8-29 23:41 | 显示全部楼层
(4)把硬件开发板和软件平台结合起来,对视频监控智能小车整个系统进行了整体测试。对测试中出现的问题进行相关的改进工作,进一步提高系统工作的可靠性和稳定性。

根据提出方案的功能需求,对轮式机器人的整体结构进行设计,采用双面覆铜加硬的PCB板料作为轮式机器人的底盘,其优点是:不易变形、不易折断、轻量化、不易造成短路;选用抗干扰TT马达,其加入压敏抗组的转子可抵抗电机突然启动产生的火花干扰,避免触发信号错误,可有效降低马达启动噪音,并在启动时可提供更大电流,使马力更强;使用航模级抗滑橡胶轮胎内带海绵表面平整不易变形,在避障行走时刹车不易撞上障碍物。马达用马达锁片固定到机器人底盘上,轮子通过轴与马达相连。
 楼主| 4c1l 发表于 2022-8-29 23:44 | 显示全部楼层
其余硬件设备均固定到机器人底盘上,包括电池座、红外避障传感器、wifi模块、摄像头、STM32单片机主控模块和L298N电机驱动芯片。
 楼主| 4c1l 发表于 2022-8-29 23:47 | 显示全部楼层
具体设计细节请参考之前的博客,再次不做赘述
主程序代码
  1. #include "sys.h"       
  2. #include "delay.h"       

  3. #define EN1 PAout(2)                          //L293D控制管脚定义
  4. #define IN1 PAout(3)                          //L293D控制管脚定义
  5. #define IN2 PAout(4)                          //L293D控制管脚定义
  6. #define EN2 PAout(7)                          //L293D控制管脚定义
  7. #define IN3 PAout(6)                          //L293D控制管脚定义
  8. #define IN4 PAout(5)                          //L293D控制管脚定义

  9. #define BEEP PBout(5)                         //蜂鸣器控制管脚定义

  10. #define KEY1 PAin(8)                                      //功能按键对应的管脚

  11. #define XJ_LEFT PAin(13)                      //左边循迹信号           
  12. #define XJ_RIGHT PAin(14)                     //右边循迹信号

  13. u8 pwmval_left  = 0;                          //左电机调速变量
  14. u8 pwmval_right = 0;                          //右电机调速变量

  15. u8 pwmval_left_init  = 6;                     //左电机速度值  
  16. u8 pwmval_right_init = 6;                     //右电机速度值

  17. u8 right_pwm = 1;                                    //左电机调速开关   
  18. u8 left_pwm  = 1;                                                //右电机调速开关      

  19. void Motor_Init(void);                        //电机接口初始化
  20. void forward(void);                           //小车前进控制函数
  21. void back(void);                                                //小车后退控制函数
  22. void left_turn(void);                    //向右转  
  23. void stop(void);                                                          //向左转
  24. void right_turn(void);                                      //停车
  25. void circle_left(void);                                    //原地向左转圈
  26. void circle_right(void);                                         //原地向右转圈
  27. void left_moto(void);                         //左电机调速函数
  28. void right_moto(void);                        //右电机调速函数
  29. void Timerx_Init(u16 arr,u16 psc);            //定时器初始化函数
  30. void Beep_Init(void);                         //蜂鸣器接口初始化
  31. void Key_Init(void);                          //按键接口初始化函数
  32. void Key_Scan(void);                          //按键1扫描函数
  33. void Xj_Init(void);                           //循迹信号接口初始化函数
  34. /***********************************************************
  35.                        实验功能
  36. 智能小车按键循迹实验,智能小车上电后,按下开发板启动按键(靠
  37. 近电源开关那个)小车开始循迹运动。要达到好的实验效果请仔细调
  38. 循迹灵敏度。

  39. 接线说明:
  40. 电机驱动线:
  41. 开发板的PA2接小车底盘的M6
  42. 开发板的PA3接小车底盘的M5
  43. 开发板的PA4接小车底盘的M4
  44. 开发板的PA5接小车底盘的M3
  45. 开发板的PA6接小车底盘的M2
  46. 开发板的PA7接小车底盘的M1

  47. 电源线:
  48. 开发板的5V接小车底盘的5V
  49. 开发板的GND接小车底盘的GND

  50. 循迹信号线:
  51. 开发板的PA13接小车底盘的H1
  52. 开发板的PA14接小车底盘的H2
  53. ***********************************************************/
  54. int main(void)
  55. {
  56. Stm32_Clock_Init(9);                         //系统时钟设置
  57. delay_init(72);                                    //延时初始化
  58. Motor_Init();                                                  //初始化与电机连接的硬件接口
  59. Timerx_Init(9,7199);                         //10Khz的计数频率,计数到9为1ms
  60. Beep_Init();                                 //蜂鸣器接口初始化                                 
  61. Key_Init();
  62. Xj_Init();
  63.        
  64. Key_Scan();                                  //按键扫描
  65.        
  66. while(1)                                               
  67. {   
  68.   if((XJ_LEFT==0)&&(XJ_RIGHT==0))             //两边都没有感应到黑线
  69.   {
  70.    forward();                                 //前进
  71.   }
  72.   else if((XJ_LEFT==1)&&(XJ_RIGHT==1))        //两边都感应到黑线(这种情况基本不会出现,主要是容错处理)
  73.   {
  74.    forward();                                 //前进
  75.   }
  76.   else
  77.   {                          
  78.    if((XJ_LEFT==1)&&(XJ_RIGHT==0))                  //右边感应到黑线  
  79.    {
  80.     delay_ms(3);
  81.           if((XJ_LEFT==1)&&(XJ_RIGHT == 0))
  82.           {
  83.            left_turn();                                          //左转
  84.           }                  
  85.    }                                                       
  86.    if((XJ_RIGHT==1)&&(XJ_LEFT==0))            //左边感应到黑线  
  87.    {
  88.     delay_ms(3);
  89.     if((XJ_RIGHT==1)&&(XJ_LEFT==0))              
  90.     {                  
  91.            right_turn();                                        //右转         
  92.            }
  93.    }
  94.   }         
  95. }         
  96. }

  97. void Beep_Init(void)                    //蜂鸣器接口初始化
  98. {
  99. RCC->APB2ENR|=1<<3;                    //使能PORTB时钟
  100.   
  101. GPIOB->CRL&=0XFF0FFFFF;
  102. GPIOB->CRL|=0X00300000;                //PB5推挽输出
  103. GPIOB->ODR|=1<<5;                      //PB5输出高       
  104. }

  105. void Xj_Init(void)
  106. {
  107. RCC->APB2ENR|=1<<2;               //使能PORTA时钟                    
  108. GPIOA->CRH&=0XFF0FFFFF;
  109. GPIOA->CRH|=0X00800000;           //PA13上拉输入
  110. GPIOA->ODR|=1<<13;                //PA13上拉       

  111. GPIOA->CRH&=0XF0FFFFFF;
  112. GPIOA->CRH|=0X08000000;           //PA14上拉输入
  113. GPIOA->ODR|=1<<14;                //PA14上拉       
  114. }

  115. void Key_Init(void)
  116. {
  117. RCC->APB2ENR|=1<<2;               //使能PORTA时钟                    
  118. GPIOA->CRH&=0XFFFFFFF0;
  119. GPIOA->CRH|=0X00000008;           //PA8上拉输入
  120. GPIOA->ODR|=1<<8;                 //PA8上拉       
  121. }

  122. void Key_Scan(void)                //按键扫描函数
  123. {
  124. LOOP:if(KEY1==0)                               //第一次判断按键是否按下
  125.       {
  126.        delay_ms(5);
  127.              if(KEY1==0)                             //第二次判断按键是否按下
  128.        {
  129.                     BEEP = 0;                               //蜂鸣器响
  130.                     while(KEY1 == 0);          //等待按键松开
  131.                     BEEP = 1;                         //蜂鸣器不响
  132.        }
  133.              else
  134.              {
  135.               goto LOOP;                 //如果第一次判断时按键没有按下则重新扫描
  136.              }
  137.       }
  138.       else
  139.       {
  140.        goto LOOP;                         //如果第二次判断时按键没有按下则重新扫描
  141.       }
  142. }

  143. void Motor_Init(void)
  144. {
  145. RCC->APB2ENR|=1<<2;                    //使能PORTA接口时钟
  146.   
  147. GPIOA->CRL&=0XFFFFF0FF;
  148. GPIOA->CRL|=0X00000300;                //PA2推挽输出
  149. GPIOA->ODR|=1<<2;                      //PA2输出高电平
  150.        
  151. GPIOA->CRL&=0XFFFF0FFF;
  152. GPIOA->CRL|=0X00003000;                //PA3推挽输出
  153. GPIOA->ODR|=1<<3;                      //PA3输出高电平
  154.        
  155. GPIOA->CRL&=0XFFF0FFFF;
  156. GPIOA->CRL|=0X00030000;                //PA4推挽输出
  157. GPIOA->ODR|=1<<4;                      //PA4输出高电平

  158. GPIOA->CRL&=0XFF0FFFFF;
  159. GPIOA->CRL|=0X00300000;                //PA5推挽输出
  160. GPIOA->ODR|=1<<5;                      //PA5输出高电平
  161.        
  162. GPIOA->CRL&=0XF0FFFFFF;
  163. GPIOA->CRL|=0X03000000;                //PA6推挽输出
  164. GPIOA->ODR|=1<<6;                      //PA6输出高电平       

  165. GPIOA->CRL&=0X0FFFFFFF;
  166. GPIOA->CRL|=0X30000000;                //PA7推挽输出
  167. GPIOA->ODR|=1<<7;                      //PA7输出高电平
  168. }

  169. void forward(void)                      //小车前进控制函数
  170. {
  171. IN1 = 1;
  172. IN2 = 0;

  173. IN3 = 1;
  174. IN4 = 0;  
  175. }

  176. void back(void)                                            //小车后退控制函数
  177. {
  178. IN1 = 0;
  179. IN2 = 1;

  180. IN3 = 0;
  181. IN4 = 1;
  182. }

  183. void left_turn(void)                          //向左转
  184. {  
  185. IN1 = 1;
  186. IN2 = 0;

  187. IN3 = 0;
  188. IN4 = 0;
  189. }

  190. void right_turn(void)                                //向右转  
  191. {
  192. IN1 = 0;
  193. IN2 = 0;

  194. IN3 = 1;
  195. IN4 = 0;   
  196. }

  197. void stop(void)                                            //停车
  198. {
  199. IN1 = 0;
  200. IN2 = 0;   

  201. IN3 = 0;
  202. IN4 = 0;
  203. }

  204. void circle_left(void)                              //原地向左转圈
  205. {
  206. IN1 = 1;
  207. IN2 = 0;

  208. IN3 = 0;
  209. IN4 = 1;
  210. }

  211. void circle_right(void)                                     //原地向右转圈
  212. {
  213. IN1 = 0;
  214. IN2 = 1;   

  215. IN3 = 1;
  216. IN4 = 0;   
  217. }

  218. void left_moto(void)                    //左电机调速函数
  219. {  
  220. if(left_pwm)
  221. {
  222.   if(pwmval_left <= pwmval_left_init)
  223.   {
  224.    EN1 = 1;
  225.   }
  226.   else
  227.   {
  228.    EN1 = 0;
  229.   }
  230.   if(pwmval_left >= 20)
  231.   {
  232.    pwmval_left = 0;
  233.   }
  234. }
  235. else   
  236. {
  237.   EN1 = 0;                     
  238. }
  239. }

  240. void right_moto(void)                   //右电机调速函数
  241. {
  242. if(right_pwm)
  243. {
  244.   if(pwmval_right <= pwmval_right_init)                  
  245.   {
  246.    EN2 = 1;                                                           
  247.   }
  248.   else if(pwmval_right > pwmval_right_init)
  249.   {
  250.    EN2 = 0;
  251.   }
  252.   if(pwmval_right >= 20)
  253.   {
  254.    pwmval_right = 0;
  255.   }
  256. }
  257. else   
  258. {
  259.   EN2 = 0;                                                      
  260. }
  261. }

  262. //定时器3中断服务程序         
  263. void TIM3_IRQHandler(void)
  264. {                                                                   
  265. if(TIM3->SR&0X0001)                          //溢出中断
  266. {
  267.   pwmval_left  = pwmval_left  + 1;
  268.   pwmval_right = pwmval_right + 1;

  269.   left_moto();
  270.   right_moto();
  271. }                                  
  272. TIM3->SR&=~(1<<0);                           //清除中断标志位             
  273. }

  274. //通用定时器中断初始化
  275. //这里时钟选择为APB1的2倍,而APB1为36M
  276. //arr:自动重装值。
  277. //psc:时钟预分频数
  278. //这里使用的是定时器3!
  279. void Timerx_Init(u16 arr,u16 psc)
  280. {
  281. RCC->APB1ENR|=1<<1;                    //TIM3时钟使能   
  282. TIM3->ARR=arr;                         //设定计数器自动重装值//刚好1ms   
  283. TIM3->PSC=psc;                         //预分频器7200,得到10Khz的计数时钟
  284. //这两个东东要同时设置才可以使用中断
  285. TIM3->DIER|=1<<0;                      //允许更新中断                                  
  286. TIM3->CR1|=0x01;                       //使能定时器3
  287. MY_NVIC_Init(1,3,TIM3_IRQChannel,2);   //抢占1,子优先级3,组2                                                                         
  288. }

 楼主| 4c1l 发表于 2022-8-29 23:49 | 显示全部楼层
中断:
  1. #include "sys.h"
  2.   
  3. //设置向量表偏移地址
  4. //NVIC_VectTab:基址
  5. //Offset:偏移量
  6. //CHECK OK
  7. //091207
  8. void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)         
  9. {
  10. //检查参数合法性
  11. assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
  12. assert_param(IS_NVIC_OFFSET(Offset));           
  13. SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);             //设置NVIC的向量表偏移寄存器
  14. //用于标识向量表是在CODE区还是在RAM区
  15. }

  16. //设置NVIC分组
  17. //NVIC_Group:NVIC分组 0~4 总共5组
  18. //CHECK OK
  19. //091209
  20. void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)         
  21. {
  22. u32 temp,temp1;          
  23. temp1=(~NVIC_Group)&0x07;                                       //取后三位
  24. temp1<<=8;
  25. temp=SCB->AIRCR;                                                //读取先前的设置
  26. temp&=0X0000F8FF;                                               //清空先前分组
  27. temp|=0X05FA0000;                                               //写入钥匙
  28. temp|=temp1;          
  29. SCB->AIRCR=temp;                                                //设置分组                                                        
  30. }

  31. //设置NVIC
  32. //NVIC_PreemptionPriority:抢占优先级
  33. //NVIC_SubPriority       :响应优先级
  34. //NVIC_Channel           :中断编号
  35. //NVIC_Group             :中断分组 0~4
  36. //注意优先级不能超过设定的组的范围!否则会有意想不到的错误
  37. //组划分:
  38. //组0:0位抢占优先级,4位响应优先级
  39. //组1:1位抢占优先级,3位响应优先级
  40. //组2:2位抢占优先级,2位响应优先级
  41. //组3:3位抢占优先级,1位响应优先级
  42. //组4:4位抢占优先级,0位响应优先级
  43. //NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
  44. //CHECK OK
  45. //100329
  46. void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)         
  47. {
  48. u32 temp;       
  49. u8 IPRADDR=NVIC_Channel/4;                                    //每组只能存4个,得到组地址
  50. u8 IPROFFSET=NVIC_Channel%4;                                  //在组内的偏移
  51. IPROFFSET=IPROFFSET*8+4;                                      //得到偏移的确切位置
  52. MY_NVIC_PriorityGroupConfig(NVIC_Group);                      //设置分组
  53. temp=NVIC_PreemptionPriority<<(4-NVIC_Group);          
  54. temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
  55. temp&=0xf;                                                    //取低四位

  56. if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;            //使能中断位(要清除的话,相反操作就OK)
  57. else NVIC->ISER[1]|=1<<(NVIC_Channel-32);   
  58. NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;                         //设置响应优先级和抢断优先级                                                           
  59. }

  60. //外部中断配置函数
  61. //只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
  62. //参数:GPIOx:0~6,代表GPIOA~G;BITx:需要使能的位;TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发
  63. //该函数一次只能配置1个IO口,多个IO口,需多次调用
  64. //该函数会自动开启对应中断,以及屏蔽线   
  65. //待测试...
  66. void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)
  67. {
  68. u8 EXTADDR;
  69. u8 EXTOFFSET;
  70. EXTADDR=BITx/4;                                              //得到中断寄存器组的编号
  71. EXTOFFSET=(BITx%4)*4;

  72. RCC->APB2ENR|=0x01;                                          //使能io复用时钟

  73. AFIO->EXTICR[EXTADDR]&=~(0x000F<<EXTOFFSET);                 //清除原来设置!!!
  74. AFIO->EXTICR[EXTADDR]|=GPIOx<<EXTOFFSET;                     //EXTI.BITx映射到GPIOx.BITx
  75.        
  76. //自动设置
  77. EXTI->IMR|=1<<BITx;                                          //开启line BITx上的中断
  78. if(TRIM&0x01)EXTI->FTSR|=1<<BITx;                            //line BITx上事件下降沿触发
  79. if(TRIM&0x02)EXTI->RTSR|=1<<BITx;                            //line BITx上事件上升降沿触发
  80. }

  81. //不能在这里执行所有外设复位!否则至少引起串口不工作.                    
  82. //把所有时钟寄存器复位
  83. //CHECK OK
  84. //091209
  85. void MYRCC_DeInit(void)
  86. {                                                                                                                            
  87. RCC->APB1RSTR = 0x00000000;//复位结束                         
  88. RCC->APB2RSTR = 0x00000000;
  89.           
  90. RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.          
  91. RCC->APB2ENR = 0x00000000; //外设时钟关闭.                          
  92. RCC->APB1ENR = 0x00000000;   
  93. RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                                                                                                                                  
  94. RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]                                         
  95. RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
  96. RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP                     
  97. RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
  98. RCC->CIR = 0x00000000;     //关闭所有中断

  99. //配置向量表                                  
  100. #ifdef  VECT_TAB_RAM
  101.          MY_NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
  102. #else   
  103.          MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  104. #endif
  105. }

  106. //THUMB指令不支持汇编内联
  107. //采用如下方法实现执行汇编指令WFI
  108. //CHECK OK
  109. //091209
  110. __asm void WFI_SET(void)
  111. {
  112. WFI;   
  113. }

  114. //进入待机模式         
  115. //check ok
  116. //091202
  117. void Sys_Standby(void)
  118. {
  119. SCB->SCR|=1<<2;                 //使能SLEEPDEEP位 (SYS->CTRL)          
  120. RCC->APB1ENR|=1<<28;            //使能电源时钟            
  121. PWR->CSR|=1<<8;                 //设置WKUP用于唤醒
  122. PWR->CR|=1<<2;                  //清除Wake-up 标志
  123. PWR->CR|=1<<1;                  //PDDS置位                  
  124. WFI_SET();                                               //执行WFI指令                 
  125. }          
  126.    
  127. //系统软复位
  128. //CHECK OK
  129. //091209
  130. void Sys_Soft_Reset(void)
  131. {   
  132. SCB->AIRCR =0X05FA0000|(u32)0x04;          
  133. }

  134. //JTAG模式设置,用于设置JTAG的模式
  135. //mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
  136. //CHECK OK       
  137. //100818                  
  138. void JTAG_Set(u8 mode)
  139. {
  140. u32 temp;
  141. temp=mode;
  142. temp<<=25;
  143. RCC->APB2ENR|=1<<0;              //开启辅助时钟          
  144. AFIO->MAPR&=0XF8FFFFFF;          //清除MAPR的[26:24]
  145. AFIO->MAPR|=temp;                //设置jtag模式
  146. }

  147. //系统时钟初始化函数
  148. //pll:选择的倍频数,从2开始,最大值为16       
  149. //CHECK OK
  150. //091209
  151. void Stm32_Clock_Init(u8 PLL)
  152. {
  153. unsigned char temp=0;   
  154. MYRCC_DeInit();                              //复位并配置向量表
  155. RCC->CR|=0x00010000;             //外部高速时钟使能HSEON
  156. while(!(RCC->CR>>17));           //等待外部时钟就绪
  157. RCC->CFGR=0X00000400;            //APB1=DIV2;APB2=DIV1;AHB=DIV1;
  158. PLL-=2;//抵消2个单位
  159. RCC->CFGR|=PLL<<18;              //设置PLL值 2~16
  160. RCC->CFGR|=1<<16;                      //PLLSRC ON
  161. FLASH->ACR|=0x32;                      //FLASH 2个延时周期

  162. RCC->CR|=0x01000000;             //PLLON
  163. while(!(RCC->CR>>25));           //等待PLL锁定
  164. RCC->CFGR|=0x00000002;           //PLL作为系统时钟         
  165. while(temp!=0x02)                //等待PLL作为系统时钟设置成功
  166. {   
  167.         temp=RCC->CFGR>>2;
  168.         temp&=0x03;
  169. }   
  170. }                    

 楼主| 4c1l 发表于 2022-8-29 23:49 | 显示全部楼层
IO口设置:
  1. #ifndef __SYS_H
  2. #define __SYS_H         
  3. #include <stm32f10x_map.h>
  4. #include <stm32f10x_nvic.h>
  5.   
  6. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
  7. #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
  8. #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
  9. //IO口地址映射
  10. #define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
  11. #define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
  12. #define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C
  13. #define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
  14. #define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C
  15. #define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C   
  16. #define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C   

  17. #define GPIOA_IDR_Addr    (GPIOA_BASE+8)  //0x40010808
  18. #define GPIOB_IDR_Addr    (GPIOB_BASE+8)  //0x40010C08
  19. #define GPIOC_IDR_Addr    (GPIOC_BASE+8)  //0x40011008
  20. #define GPIOD_IDR_Addr    (GPIOD_BASE+8)  //0x40011408
  21. #define GPIOE_IDR_Addr    (GPIOE_BASE+8)  //0x40011808
  22. #define GPIOF_IDR_Addr    (GPIOF_BASE+8)  //0x40011A08
  23. #define GPIOG_IDR_Addr    (GPIOG_BASE+8)  //0x40011E08

  24. //IO口操作,只对单一的IO口
  25. #define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出
  26. #define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入

  27. #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出
  28. #define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入

  29. #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出
  30. #define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入

  31. #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出
  32. #define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入

  33. #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出
  34. #define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

  35. #define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出
  36. #define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

  37. #define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出
  38. #define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入
  39. /
  40. //Ex_NVIC_Config专用定义
  41. #define GPIO_A 0
  42. #define GPIO_B 1
  43. #define GPIO_C 2
  44. #define GPIO_D 3
  45. #define GPIO_E 4
  46. #define GPIO_F 5
  47. #define GPIO_G 6
  48. #define FTIR   1                               //下降沿触发
  49. #define RTIR   2                               //上升沿触发
  50. /
  51. //JTAG模式设置定义
  52. #define JTAG_SWD_DISABLE   0X02
  53. #define SWD_ENABLE         0X01
  54. #define JTAG_SWD_ENABLE    0X00       
  55. /  
  56. void Stm32_Clock_Init(u8 PLL);                            //时钟初始化  
  57. void Sys_Soft_Reset(void);                                //系统软复位
  58. void Sys_Standby(void);                                   //待机模式        
  59. void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset);//设置偏移地址
  60. void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group);          //设置NVIC分组
  61. void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group);//设置中断
  62. void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM);            //外部中断配置函数(只对GPIOA~G)
  63. void JTAG_Set(u8 mode);
  64. #endif

sdCAD 发表于 2022-9-5 13:54 | 显示全部楼层
这个可以做成平衡小车吗
gygp 发表于 2022-9-5 15:07 | 显示全部楼层
这个可以摄像头巡线吗
uytyu 发表于 2022-9-8 19:24 | 显示全部楼层
如何快速实现扫描黑线
touser 发表于 2022-9-8 20:23 | 显示全部楼层
红外检测模块的实现的
yujielun 发表于 2022-9-11 14:44 | 显示全部楼层
wifi可以传输视频吗
jonas222 发表于 2022-9-11 16:48 | 显示全部楼层
智能小车的还是比较不错的。
youtome 发表于 2022-9-11 18:26 | 显示全部楼层
使用了pid的算法了吗
Bowclad 发表于 2022-9-11 20:52 | 显示全部楼层
红外检查模块
saservice 发表于 2022-9-12 13:09 | 显示全部楼层
使用定时器了吗
beacherblack 发表于 2022-10-5 17:19 | 显示全部楼层
基于STM32F103C8T6的黑线寻迹小车,总算成功了。
weifeng90 发表于 2022-10-5 17:21 来自手机 | 显示全部楼层
这个代码测试过嘛?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

701

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

63

主题

701

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部