本文描述了一个由STM32微处理器、步进电机、蓝牙,L298N等模块构成的。该系统采用STM32微处理器为核心,在MDK环境下进行编程,通知控制L298N模块IN1~IN4引脚的高低电平进而控制电机的转动方向,使小车产生不同的转动模式。控制小车的转动模式通过蓝牙模块来实现,利用手机蓝牙助手和蓝牙模块相通,进而控制小车的各种运转模式。 代码、蓝牙Android apk地址:https://github.com/daohewang/Bluetooth-intelligent-car
下面的图把核心连接部分都画出来了(其他部分按要求接就可以了,Vcc接电源,GND接地即可),图画的有点丑,希望大家不要介意呀(>-<)
使用微控制器为STM32F103RC,其芯片引脚如图所示
2. JDY 30蓝牙模块 JDY-30 透传模块是基于蓝牙 2.1 协议标准,工作频段为 2.4GHZ 范围,具有信号强、数据传输快、性能稳定等特性。支持蓝牙 SPP 串口协议,内置 PCB 天线,支持 UART 接口,蓝牙 Class 2,数据传输比 BLE 蓝牙快、可达到几十 K 每秒以上的速率。如图3.2所示。
实物图:
引脚功能说明 1 、 UART-TX 串口输出,接开发板上的UART-Rx,电平为 TTL 电平 2 、 UART-RX 串口输入,接开发板上的UART-Tx,电平为 TTL 电平 3 、 VCC 3.3V 电源 4 、 GND 电源地
这里的蓝牙助手使用方法要情调一下,可能有些同学不太会,点击右上角的连接按钮,先让手机连上蓝牙模块,一般连上了蓝牙模块上的灯都不会闪烁。以此判断有没有连接上。接着就是编辑键盘的小车的运动方式了,按照下面的来设置就可以了。这里的数字是我代码设置好的,可以按照自己的要求填写。
首先对前进,后退,左转,右转,停止进行宏定义,单片机接收到蓝牙串口的相应指令,然后在if语句中进行比较,如果有相对应的,触发相对应的宏定义。流程图如图所示。在串口USART1中接收到的数据进行比较,暂停、前进、后退、左转、右转、原地左转,原地右转。启动字符为 “0”,“1”,“2”,“3”,“4”,“5”,“6”。
1.motor.h
#ifndef _MOTOR_H
#define _MOTOR_H
void MotorInit(void);
void Turnleft(void);
void Turnright(void);
void Turnback(void);
void Turnfront(void);
void Stop(void);
void Leftaround(void);
void Rightaround(void);
#endif
2. motor.c
#include "STM32F10X.h"
#include "motor.h"
void MotorInit(void)
{
//初始化和使能单片机上的GPIO端口,保证可以正常给端口高低电平
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_6);
// MOTOR_APB_PERIPH_FUNG(MOTOr_APB_PORT , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD, GPIO_Pin_2);
}
//停止模式
void Stop(void)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_10);
GPIO_ResetBits(GPIOC,GPIO_Pin_11);
GPIO_ResetBits(GPIOC,GPIO_Pin_12);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
//左转模式 -> 左电机正转,右电机反转
void Turnleft(void)
{
GPIO_SetBits(GPIOC,GPIO_Pin_10);
GPIO_ResetBits(GPIOC,GPIO_Pin_11);
GPIO_ResetBits(GPIOC,GPIO_Pin_12);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
}
//右转模式 -> 左电机反转,右电机正转
void Turnright(void)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_10);
GPIO_SetBits(GPIOC,GPIO_Pin_11);
GPIO_SetBits(GPIOC,GPIO_Pin_12);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
}
//后退模式 -> 左电机反转,右电机反转
void Turnback(void)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_10);
GPIO_SetBits(GPIOC,GPIO_Pin_11);
GPIO_ResetBits(GPIOC,GPIO_Pin_12);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_8);
}
//前进模式 -> 左电机正转,右电机正转
void Turnfront(void)
{
GPIO_SetBits(GPIOC,GPIO_Pin_10);
GPIO_ResetBits(GPIOC,GPIO_Pin_11);
GPIO_SetBits(GPIOC,GPIO_Pin_12);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
}
//以左电机为中心原地左转
void Leftaround(void)
{
GPIO_SetBits(GPIOC,GPIO_Pin_10);
GPIO_ResetBits(GPIOC,GPIO_Pin_11);
GPIO_SetBits(GPIOC,GPIO_Pin_12);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
}
//以右电机为中心原地右转
void Rightaround(void)
{
GPIO_SetBits(GPIOC,GPIO_Pin_10);
GPIO_SetBits(GPIOC,GPIO_Pin_11);
GPIO_SetBits(GPIOC,GPIO_Pin_12);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
3. main函数
#include "MOTOR.h"
#include "stm32f10x.h" //官方库
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_it.h"
#include <stdio.h>
/*
#ifdef->endif的内容部分和PUTCHAR_PROTOTYPE{}的内容属于C语言的语法规则引入,
所以头部必须引入#include<stdio.h>,这样子的话C语言的语法就可以完美引用
*/
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
//中断服务函数
u8 i;
u8 flag; //定义一个标志位
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) //检查指定的 USART1 中断发生与否
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除 USART1 的中断待处理位
GPIO_ResetBits(GPIOC,GPIO_Pin_6); //设置LED灯作为中断发生与否的指示灯
i= USART_ReceiveData(USART1); //返回 USART1 最近接收到的数据
//if语句的内容部分可以保证蓝牙接收到的flag数据是正确的,如果不加的话会导致接收不到正确的数据
if(i=='0')
{
flag=0;
}
if(i=='1')
{
flag=1;
}
if(i=='2')
{
flag=2;
}
if(i=='3')
{
flag=3;
}
if(i=='4')
{
flag=4;
}
if(i=='5')
{
flag=5;
}
if(i=='6')
{
flag=6;
}
}
// USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
int main(void)
{
//利用中断进行蓝牙的收发
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
// USART_DeInit(USART1); //复位串口1
// USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
/* USARTx configured as follow:
- BaudRate = 9600 baud 波特率
- Word Length = 8 Bits 数据长度
- One Stop Bit 停止位
- No parity 校验方式
- Hardware flow control disabled (RTS and CTS signals) 硬件控制流
- Receive and transmit enabled 使能发送和接收
*/
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
//Usart1 NVIC 配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_Cmd(USART1, ENABLE); //使能串口
MotorInit();
//蓝牙数据接收判断函数
while(1)
{
switch(flag)
{
case 0: Stop(); break ;
case 1: Turnleft(); break ;
case 2: Turnright(); break ;
case 3: Turnback(); break ;
case 4: Turnfront(); break ;
case 5: Leftaround(); break ;
case 6: Rightaround(); break ;
default: Stop(); break ;
}
}
}
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* 循环等待直到发送结束*/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
return ch;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/180707.html原文链接:https://javaforall.cn