摘要:同時,該模塊中包括小車的加減速以及小車的轉向功能。在串口中斷處理程序中,由于我設定的主機指令以一個字節為單位,故串口檢測到一個字節的接收時就立即判斷當前指令對應的動作,指令與小車動作的映射見上位機編寫部分。
暑假無聊,手頭又有一個閑置的單片機一直放著,就想著做個遙控小車出來,復習一下單片機嵌入式編程。該遙控小車項目參考CSDN博主你就叫我李大帥的文章:STM32智能遙控小車,超詳細-附下載直接可以用,雙電源跑賊快!。自己在原文的基礎上添加了電腦端的控制,然后做了一個安卓定制軟件來控制小車。
注:
最終實物圖:
硬件方面與李大帥博主的硬件組成差不多:使用兩個L298N電機驅動模塊驅動四個電機,STM32開發板用來控制這兩個電機驅動模塊,并通過JDY-31藍牙透傳模塊與手機或電腦通信。整體采用兩個獨立電源分別為單片機和L298N供電。
該模塊用于驅動電機,一個L298N可以驅動兩個電機,有關L298N模塊的講解可以看這個視頻:l298n電機驅動模塊 電機正反轉 電機調速。下圖為L298N與單片機的連接示意圖。
左側L298N:
右側L298N
說明:
JDY-31這個藍牙模塊屬于透明傳輸模塊,意思就是在使用時可以不用關心藍牙協議的細節,連接好以后可以直接將其當做串口使用。該模塊的RXD與TXD連接至單片機的UART接口,連接示意圖如下圖所示:
說明:
我使用了兩塊獨立電源,4個干電池構成6.5V電壓給單片機供電,我所購買的單片機上有DCDC降壓芯片,能將6.5V降為3.3V供單片機使用。第二塊獨立電源由一個12V鋰電池提供,為L298N供電。
6.5V電源:
12V電源:
我采用的單片機型號為STM32F407VET6,這個并不是很重要的,使用其他單片機型號找到對應的固件庫也能完成這樣的功能。
下面部分為程序中主要程序的介紹,詳細代碼見百度網盤:[下載地址]。
程序結構目錄如下:
代碼片段:
int main(void){ //設置外部中斷優先組 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //各部分的初始化 uart_init(9600); delay_init(168); LED_Init(); Bluetooth_Init(); SPEEDER_Init(); MTR_GPIOInit(); LED0 = 1; //主程序 while(1) { if(BLUTOOTH_STATE) { LED0 = 0; delay_ms(100); LED0 = 1; delay_ms(100); } else { LED0 = 0; MTR_CarBrakeAll(); } }}
代碼說明:
代碼片段:
#include "bluetooth.h"#include "delay.h" void Bluetooth_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE時鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //STATE連接的引腳PE0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通輸入模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//down pull GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE}
說明:
#define BLUTOOTH_STATE GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_0) //PE0
代碼片段:
#include "motor.h"//剎車void MTR_CarBrakeAll(void){ MTR1_BRAKE; MTR2_BRAKE; MTR3_BRAKE; MTR4_BRAKE;}//前進void MTR_CarGo(void){ MTR1_ROTA_F; MTR2_ROTA_F; MTR3_ROTA_F; MTR4_ROTA_F;}//后退void MTR_CarBack(void){ MTR1_ROTA_B; MTR2_ROTA_B; MTR3_ROTA_B; MTR4_ROTA_B;}//順時針轉void MTR_CarCW(void){ MTR1_ROTA_F; MTR2_ROTA_F; MTR3_ROTA_B; MTR4_ROTA_B;}//逆時針轉void MTR_CarCCW(void){ MTR1_ROTA_B; MTR2_ROTA_B; MTR3_ROTA_F; MTR4_ROTA_F;}//電機驅動控制初始化void MTR_GPIOInit(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(MTR1_GPIO_CLK|MTR2_GPIO_CLK|MTR3_GPIO_CLK|MTR4_GPIO_CLK,ENABLE);//時鐘 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//推挽輸出 //電機1 GPIO_InitStructure.GPIO_Pin = MTR1_GPIO_PIN; GPIO_Init(MTR1_GPIO_PORT, &GPIO_InitStructure); //電機2 GPIO_InitStructure.GPIO_Pin = MTR2_GPIO_PIN; GPIO_Init(MTR2_GPIO_PORT, &GPIO_InitStructure); //電機3 GPIO_InitStructure.GPIO_Pin = MTR3_GPIO_PIN; GPIO_Init(MTR3_GPIO_PORT, &GPIO_InitStructure); //電機4 GPIO_InitStructure.GPIO_Pin = MTR4_GPIO_PIN; GPIO_Init(MTR4_GPIO_PORT, &GPIO_InitStructure); //小車剎車 MTR_CarBrakeAll();}
說明:
代碼片段:
#include "sys.h"#include "speeder.h"u16 SPEED_LEVEL = SPEED_LEVEL1;u8 CAR_STATE = STRAIGHT_STATE;//GPIO初始化static void SPEEDER_GPIO_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(SPEEDER_GPIO_CLK,ENABLE);//時鐘 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//推挽輸出 //初始化GPIO 將復用的引腳與對應的定時器綁定在一起。 GPIO_InitStructure.GPIO_Pin = SPEEDER_GPIO_PIN; GPIO_Init(SPEEDER_GPIO_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(SPEEDER_GPIO_PORT,GPIO_PinSource12,GPIO_AF_TIM4); GPIO_PinAFConfig(SPEEDER_GPIO_PORT,GPIO_PinSource13,GPIO_AF_TIM4); GPIO_PinAFConfig(SPEEDER_GPIO_PORT,GPIO_PinSource14,GPIO_AF_TIM4); GPIO_PinAFConfig(SPEEDER_GPIO_PORT,GPIO_PinSource15,GPIO_AF_TIM4);}//定時器初始化static void SPEEDER_TIM_Init(void){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(GENERAL_TIM_CLK,ENABLE); /*--------------------TIME BASE 結構體初始化-------------------------*/ TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period; //自動重裝載的值 TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler; //預分頻值 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數 TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // 初始化定時器 TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure); /*--------------------輸出比較結構體初始化-------------------*/ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 配置為PWM2模式 計數器值大于occr時輸出有效信號 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 輸出通道電平極性配置 有效信號為高電平 TIM_OCInitStructure.TIM_Pulse = SPEED_LEVEL; //比較的值:0 TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure); // 輸出比較通道 1 TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable); TIM_OCInitStructure.TIM_Pulse = SPEED_LEVEL; TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure); // 輸出比較通道 2 TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable); TIM_OCInitStructure.TIM_Pulse = SPEED_LEVEL; TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure); // 輸出比較通道 3 TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable); TIM_OCInitStructure.TIM_Pulse = SPEED_LEVEL; TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure); // 輸出比較通道 4 TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(GENERAL_TIM,ENABLE); TIM_Cmd(GENERAL_TIM, ENABLE); // 使能定時器}//整體的使能void SPEEDER_Init(void){ SPEEDER_GPIO_Init(); SPEEDER_TIM_Init(); CAR_STATE = STRAIGHT_STATE;}//向右轉void SET_RIGHT_TURN(void){ CAR_STATE = RIGHT_STATE; TIM_SetCompare1(GENERAL_TIM,SPEED_LEVEL); TIM_SetCompare2(GENERAL_TIM,SPEED_LEVEL); TIM_SetCompare3(GENERAL_TIM,0); TIM_SetCompare4(GENERAL_TIM,0);}//向左轉void SET_LEFT_TURN(void){ CAR_STATE = LEFT_STATE; TIM_SetCompare1(GENERAL_TIM,0); TIM_SetCompare2(GENERAL_TIM,0); TIM_SetCompare3(GENERAL_TIM,SPEED_LEVEL); TIM_SetCompare4(GENERAL_TIM,SPEED_LEVEL);}//變直道void RESET_DIRECTION(void){ CAR_STATE = STRAIGHT_STATE; TIM_SetCompare1(GENERAL_TIM,SPEED_LEVEL); TIM_SetCompare2(GENERAL_TIM,SPEED_LEVEL); TIM_SetCompare3(GENERAL_TIM,SPEED_LEVEL); TIM_SetCompare4(GENERAL_TIM,SPEED_LEVEL);}//根據當前的小車狀態將當前的速度等級賦值到對應的定時器中。static void RESET_SPEED_LEVEL(void){ switch(CAR_STATE){ case STRAIGHT_STATE: RESET_DIRECTION(); break; case LEFT_STATE: SET_LEFT_TURN(); break; case RIGHT_STATE: SET_RIGHT_TURN(); break; }}//變速:加速void SPEED_UP(void){ switch(SPEED_LEVEL){ case SPEED_LEVEL0: SPEED_LEVEL = SPEED_LEVEL1; break; case SPEED_LEVEL1: SPEED_LEVEL = SPEED_LEVEL2; break; case SPEED_LEVEL2: SPEED_LEVEL = SPEED_LEVEL3; break; case SPEED_LEVEL3: SPEED_LEVEL = SPEED_LEVEL3; break; } RESET_SPEED_LEVEL();}//變速:減速void SPEED_DOWN(void){ switch(SPEED_LEVEL){ case SPEED_LEVEL0: SPEED_LEVEL = SPEED_LEVEL0; break; case SPEED_LEVEL1: SPEED_LEVEL = SPEED_LEVEL0; break; case SPEED_LEVEL2: SPEED_LEVEL = SPEED_LEVEL1; break; case SPEED_LEVEL3: SPEED_LEVEL = SPEED_LEVEL2; break; } RESET_SPEED_LEVEL();}
說明:
代碼部分:
void USART1_IRQHandler(void) //串口1中斷服務程序{ uint8_t CMD = 0;//接收的命令 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ USART_ClearFlag(USART1,USART_FLAG_RXNE); USART_ClearITPendingBit(USART1,USART_IT_RXNE); CMD = USART_ReceiveData(USART1);//讀取一個字節 switch(CMD){ case 0x00: RESET_DIRECTION(); MTR_CarGo(); printf("forward/r/n"); break; case 0x01: RESET_DIRECTION(); MTR_CarBack(); printf("back/r/n"); break; case 0x02: SET_RIGHT_TURN(); printf("right turn/r/n"); break; case 0x03: SET_LEFT_TURN(); printf("left turn/r/n"); break; case 0x04: MTR_CarCW(); printf("right CW/r/n"); break; case 0x05: MTR_CarCCW(); printf("left CW/r/n"); break; case 0x06://==================加速 SPEED_UP(); printf("speed up/r/n"); break; case 0x07://===================減速 SPEED_DOWN(); printf("speed down/r/n"); break; case 0x0a: RESET_DIRECTION(); printf("reset straight/r/n"); break; case 0xff: MTR_CarBrakeAll(); printf("stop/r/n"); break; case 0x1f: //================ 測試連接 printf("connect successfully"); break; } }}
說明:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119768.html
摘要:基于開發的軟件包導師汪禮超學員崔林威摘要騰訊物聯網操作系統是騰訊面向物聯網領域開發的實時操作系統,具有低功耗,低資源占用,模塊化,可裁剪等特性。圖中斷函數處理進行生成工程配置,按如下界面進行配置,最后點擊,并點擊。 ...
摘要:所以我必須基于自己現在的情況走出一條適合自己情況的成長路線。下位機上位機的思想下位機上位機這就是我自己探索出來的技術成長路線。對和嵌入式的朋友感興趣的朋友可以試一下我這條學習路線 ...
摘要:本文的三位作者正陽海洋阿力,是來自不同公司的工程師,將與智能小車結合,開發了一款可實時視頻遠程看房的創新性項目。用戶可以通過上位機或網頁前端控制小車前后左右移動或控制云臺調整攝像頭方向。 本文的三位作者正陽、海洋、阿力,是來自不同公司的工程師,將 Agora SDK 與智能小車結合,開發了一款可實時視頻遠程看房的創新性項目。本文將從方案設計到具體實現,詳實分享他們的開發經驗。三人也憑借...
摘要:本文的三位作者正陽海洋阿力,是來自不同公司的工程師,將與智能小車結合,開發了一款可實時視頻遠程看房的創新性項目。用戶可以通過上位機或網頁前端控制小車前后左右移動或控制云臺調整攝像頭方向。 本文的三位作者正陽、海洋、阿力,是來自不同公司的工程師,將 Agora SDK 與智能小車結合,開發了一款可實時視頻遠程看房的創新性項目。本文將從方案設計到具體實現,詳實分享他們的開發經驗。三人也憑借...
閱讀 2545·2023-04-26 01:44
閱讀 2558·2021-09-10 10:50
閱讀 1411·2019-08-30 15:56
閱讀 2250·2019-08-30 15:44
閱讀 512·2019-08-29 11:14
閱讀 3416·2019-08-26 11:56
閱讀 3018·2019-08-26 11:52
閱讀 908·2019-08-26 10:27