冰楓論壇
標題:
ARM Cortex-M4消防機器人
[打印本頁]
作者:
洪嵐峰
時間:
2023-4-3 12:54
標題:
ARM Cortex-M4消防機器人
所需零件:
ARM Cortex-M4微控制器
紅外線傳感器
煙霧傳感器
超聲波傳感器
直流馬達
輪子
陀螺儀
電池
藍牙模組
螢幕
連結腳位:
紅外線傳感器:通過數字輸入接口(DI)連接到微控制器的腳位上
煙霧傳感器:通過模擬輸入接口(A/D)連接到微控制器的腳位上
超聲波傳感器:通過數字輸入接口(DI)連接到微控制器的腳位上
直流馬達:通過PWM輸出接口連接到微控制器的腳位上
輪子:通過直流馬達控制器連接到微控制器的腳位上
陀螺儀:通過I2C介面連接到微控制器的腳位上
電池:通過電源管理模塊連接到微控制器的腳位上
藍牙模組:通過UART介面連接到微控制器的腳位上
螢幕:通過SPI介面連接到微控制器的腳位上
程式碼:
以下是ARM Cortex-M4消防機器人的示例程式碼。請注意,這只是一個示例,您可能需要進行修改以適應您的具體應用場景。
#include <stdio.h>
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_exti.h"
#include "misc.h"
#include "math.h"
// 定義陀螺儀的地址
#define GYRO_ADDRESS 0xD6
// 定義PWM輸出接口所使用的定時器和通道
#define MOTOR_TIMER TIM2
#define MOTOR_LEFT_CHANNEL TIM_OC3
#define MOTOR_RIGHT_CHANNEL TIM_OC4
// 定義超聲波傳感器的腳位
#define ULTRASONIC_TRIGGER_PIN GPIO_Pin_0
#define ULTRASONIC_ECHO_PIN GPIO_Pin_1
#define ULTRASONIC_PORT GPIOA
// 定義煙霧傳感器的腳位和ADC通
#define SMOKE_SENSOR_PIN GPIO_Pin_1
#define SMOKE_SENSOR_PORT GPIOC
#define SMOKE_SENSOR_CHANNEL ADC_Channel_11
// 定義紅外線傳感器的腳位
#define IR_SENSOR_PIN GPIO_Pin_2
#define IR_SENSOR_PORT GPIOD
// 定義螢幕的腳位
#define SCREEN_SCLK_PIN GPIO_Pin_3
#define SCREEN_MISO_PIN GPIO_Pin_4
#define SCREEN_MOSI_PIN GPIO_Pin_5
#define SCREEN_CS_PIN GPIO_Pin_6
#define SCREEN_DC_PIN GPIO_Pin_7
#define SCREEN_RST_PIN GPIO_Pin_8
#define SCREEN_PORT GPIOB
// 定義藍牙模組的UART腳位
#define BLUETOOTH_TX_PIN GPIO_Pin_9
#define BLUETOOTH_RX_PIN GPIO_Pin_10
#define BLUETOOTH_PORT GPIOA
#define BLUETOOTH_USART USART1
// 全局變量
uint16_t smoke_value = 0; // 煙霧傳感器讀取到的ADC值
float distance = 0.0; // 超聲波傳感器測量到的距離
int ir_sensor_state = 0; // 紅外線傳感器的狀態
float gyro_x = 0.0; // 陀螺儀的x軸角度
float gyro_y = 0.0; // 陀螺儀的y軸角度
float gyro_z = 0.0; // 陀螺儀的z軸角度
// 設置定時器2用於PWM輸出
void motor_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
TIM_OCInitTypeDef TIM_OCStruct;
// 啟用GPIOB和定時器2的時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 設置GPIOB的腳位為替換功能輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 設置腳位PB10和PB11為TIM2的輸出
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_TIM2);
// 設置定時器的計數模式為向上計數,時鐘頻率為84MHz,預分頻為1
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_Clock
// 設置定時器的計數模式為向上計數,時鐘頻率為84MHz,預分頻為1
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_Prescaler = 0;
TIM_BaseStruct.TIM_Period = 1000; // PWM周期為1ms
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_BaseStruct);
// 設置TIM2的通道1和通道2為PWM模式
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_Pulse = 0;
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCStruct);
TIM_OC2Init(TIM2, &TIM_OCStruct);
// 啟用TIM2的自動重載計數器和PWM輸出
TIM_Cmd(TIM2, ENABLE);
TIM_CtrlPWMOutputs(TIM2, ENABLE);
}
// 初始化煙霧傳感器
void smoke_sensor_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
// 啟用GPIOC和ADC1的時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// 設置GPIOC的腳位為類比輸入
GPIO_InitStructure.GPIO_Pin = SMOKE_SENSOR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(SMOKE_SENSOR_PORT, &GPIO_InitStructure);
// 設置ADC1的分辨率為12位,採樣時間為84周期,連續模式為啟用,單通道,掃描模式為關閉
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// 設置ADC1的頻率為84MHz / 4 = 21MHz
ADC_RegularChannelConfig(ADC1, SMOKE_SENSOR_CHANNEL, 1, ADC_SampleTime_84Cycles);
// 啟用ADC1
ADC_Cmd(ADC1, ENABLE);
}
// 讀取煙霧傳感器的數值
uint16_t read_smoke_sensor(void)
{
ADC_SoftwareStartConv(ADC1); // 啟動ADC
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET) {} // 等待轉換完成
return ADC_GetConversionValue(ADC1); // 返回轉換後的數值
}
// 初始化蜂鳴器
void buzzer_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
TIM_OCInitTypeDef TIM_OCStruct;
// 啟用GPIOC和TIM3的時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// 設置GPIOC的腳位為輸出模式
GPIO_InitStructure.GPIO_Pin = BUZZER_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(BUZZER_PORT, &GPIO_InitStructure);
// 設置TIM3的時鐘頻率為84MHz,預分頻為1,計數模式為向上計數,PWM周期為10000,預設占空比為50%
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_Prescaler = 0;
TIM_BaseStruct.TIM_Period = 10000;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_BaseStruct);
// 設置TIM3的通道1為PWM模式
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_Pulse = 5000; // 占空比為50%
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCStruct);
// 將TIM3的通道1的輸出引腳映射到GPIOC的腳位
GPIO_PinAFConfig(BUZZER_PORT, BUZZER_PIN_SOURCE, GPIO_AF_TIM3);
// 啟用TIM3的自動重載計數器和PWM輸出
TIM_Cmd(TIM3, ENABLE);
TIM_CtrlPWMOutputs(TIM3, ENABLE);
}
// 啟動蜂鳴器
void buzzer_on(void)
{
TIM_SetCompare1(TIM3, 5000); // 占空比為50%
}
// 關閉蜂鳴器
void buzzer_off(void)
{
TIM_SetCompare1(TIM3, 0); // 占空比為0%
}
// 播放警報
void play_alarm(void)
{
int i;
// 播放警報5秒鐘
for (i = 0; i <
// 播放警報
void play_alarm(void)
{
int i;
// 播放警報5秒鐘
for (i = 0; i < 5000; i++) {
buzzer_on();
delay_us(1000);
buzzer_off();
delay_us(1000);
}
}
// 初始化紅外線接收器
void ir_receiver_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 啟用GPIOB和SYSCFG的時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
// 設置GPIOB的腳位為輸入模式
GPIO_InitStructure.GPIO_Pin = IR_RECEIVER_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IR_RECEIVER_PORT, &GPIO_InitStructure);
// 將EXTI線連接到GPIOB的腳位上
SYSCFG_EXTILineConfig(IR_RECEIVER_EXTI_PORT_SOURCE, IR_RECEIVER_EXTI_PIN_SOURCE);
// 設置EXTI線的觸發模式為上升沿觸發
EXTI_InitStructure.EXTI_Line = IR_RECEIVER_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 啟用EXTI線的中斷
NVIC_InitStructure.NVIC_IRQChannel = IR_RECEIVER_EXTI_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 紅外線接收器中斷處理函數
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(IR_RECEIVER_EXTI_LINE) != RESET) {
ir_code_t ir_code;
// 讀取紅外線信號
if (ir_receiver_read(&ir_code)) {
switch (ir_code) {
case IR_CODE_UP:
// 控制機器人前進
motor_forward();
break;
case IR_CODE_DOWN:
// 控制機器人後退
motor_backward();
break;
case IR_CODE_LEFT:
// 控制機器人向左轉彎
motor_turn_left();
break;
case IR_CODE_RIGHT:
// 控制機器人向右轉彎
motor_turn_right();
break;
case IR_CODE_STOP:
// 停止機器人運動
motor_stop();
break;
case IR_CODE_ALARM:
// 播放警報
play_alarm();
break;
}
}
//
// 清除EXTI線的中斷標誌
EXTI_ClearITPendingBit(IR_RECEIVER_EXTI_LINE);
}
}
int main(void)
{
// 初始化GPIO口和PWM定時器
gpio_init();
pwm_init();
// 初始化紅外線接收器
ir_receiver_init();
// 播放啟動音效
play_startup_sound();
while (1) {
// 處理消防機器人的運動控制
// (由紅外線接收器中斷處理函數來實現)
}
}
這個示例程式碼展示了如何使用STM32的GPIO、PWM定時器和外部中斷來控制一個消防機器人。
歡迎光臨 冰楓論壇 (https://bingfong.com/)
Powered by 冰楓