USART通信stm32与openmv控制舵机

1内容简介:
openmv端执行模板匹配功能,将匹配到的模板图片编号发送给stm32端,串口接收到数据相应调用舵机旋转角度。

2.接线
openmv ------- stm32
p4(Tx) - gpiob11(RX)
p5(RX) - gpiob10(TX)
ground - ground

STM32 -------- TTL
Tx - gpiob11(RX)
RX - gpiob10(TX)
ground - ground

舵机 ------- STM32
vcc(红线)- vcc
ground - ground
信号线 - gpioa1
IMG_20250704_144230

3.openmv端代码

import sensor
import image
from image import SEARCH_EX
from pyb import UART

# 初始化摄像头
sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.QQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)

# 初始化串口
uart = UART(3, 115200)

# 加载模板
templates = []
template_to_id = {"1.pgm": 1, "3.pgm": 3, "8.pgm": 8}
for t in ["1.pgm", "3.pgm", "8.pgm"]:
    try:
        template = image.Image(t)
        templates.append(template)
    except Exception as e:
        print(f"Failed to load template {t}: {e}")

clock = time.clock()

while True:
    best_match = -1
    clock.tick()
    img = sensor.snapshot()
    # 遍历模板匹配
    for i, template in enumerate(templates):
        r = img.find_template(template, 0.70, step=4, search=SEARCH_EX)
        if r:
            img.draw_rectangle(r)
            template_name = list(template_to_id.keys())[i]
            print(template_name)  # 打印模板名字
            best_match = template_to_id.get(template_name, -1)
    # 发送匹配结果
    uart.write(f"{best_match if best_match != -1 else 0}\n")

4.stm32端代码
一.主函数:

#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "Servo.h"
#include "LED.h"

void process_num(int num);
uint8_t RxData;			//定义用于接收串口数据的变量

int main(void)
{
	
	LED_Init();		//LED初始化
	Serial_Init();		//串口初始化
	Servo_Init();
	while (1)
	{
		if (Serial_GetRxFlag() == 1)			//检查串口接收数据的标志位
		{
			RxData = Serial_GetRxData();		//获取串口接收的数据
			process_num(RxData);
//			LED2_ON();
//			Delay_ms(500);
//			LED2_OFF();
		}
			
	}
}
void process_num(int num)
{
    switch(num)
    {
        case 1:
            Servo_SetAngle(90);  // 接收到 1 时,舵机转动到 90 度
            break;
        case 3:
            Servo_SetAngle(0);   // 接收到 3 时,舵机转动到 0 度
            break;
        case 8:
            Servo_SetAngle(180); // 接收到 8 时,舵机转动到 180 度
            break;
        default:
            // 其他情况不动作
            break;
    }
}

二.Serial端usart通信:

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <Servo.h>
#include <Serial.h>

// USART3 的 TX 为 GPIOB10, RX 为 GPIOB11

uint8_t Serial_RxData;		//定义串口接收的数据变量
uint8_t Serial_RxFlag;		//定义串口接收的标志位变量

void Serial_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);                    // 将 PB10 引脚初始化为复用推挽输出
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);                    // 将 PB11 引脚初始化为上拉输入
    
    // 配置 USART
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART3, &USART_InitStructure);
    
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 开启串口接收数据的中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    // NVIC 配置
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);
    
    USART_Cmd(USART3, ENABLE); // 使能串口,串口开始运行
}

uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)			//如果标志位为1
	{
		Serial_RxFlag = 0;
		return 1;					//则返回1,并自动清零标志位
	}
	return 0;						//如果标志位为0,则返回0
}

uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;			//返回接收的数据变量
}

void USART3_IRQHandler(void)
{
	if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)		//判断是否是USART3的接收事件触发的中断
	{
		Serial_RxData = USART_ReceiveData(USART3);				//读取数据寄存器,存放在接收的数据变量
		Serial_RxFlag = 1;										//置接收标志位变量为1
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);			//清除USART1的RXNE标志位
																
	}
}
void Serial_SendByte(uint8_t Byte)
{
    USART_SendData(USART3, Byte);
    while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}

三.舵机运动代码:

#include "PWM.h"

void Servo_Init(void)
{
	PWM_Init();
}

void Servo_SetAngle(float Angle)
{
	PWM_SetCompare2(Angle / 180 * 2000 + 500);
}```
pwm端:
```#include "stm32f10x.h"                  // Device header

//ÅäÖÃTIM2µÄCH2ͨµÀ  GPIOAµÄ1Òý½Å
void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC2Init(TIM2, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare2(uint16_t Compare)
{
	TIM_SetCompare2(TIM2, Compare); //ÉèÖÃCCR
}
posted @ 2025-07-04 15:08  扎斯特小球  阅读(246)  评论(0)    收藏  举报