使用L298N对RGB灯珠进行供电,这里RGB灯珠可以换成电机来控制,因为电机声音不较大,不好操作,这里我用灯珠来替代效果基本上一样。使用串口打印获取超声波传感器获取到的数据,这里我写了一个简单的算法,来使超声波传感器的检测范围,数值为20-8000.而PWM的控制范围为0-450,使两个范围匹配,用超声波的数据来控制PWM的大小。
串口打印代码没有附上,大家可以自己寻找。
基本上没有什么难度。下附全部代码。
超声波传感器涉及到了对时钟的使用,和定时器的使用。
后续会更新一些项目制作,大家感兴趣的可以关注一些,四足机器人控制,双足连杆腿机器人(类似ROBOMASTER平衡步兵),等其他集成类项目。也会分享到B站。
本人机械硕士研究生,致力于机器人领域,之前扎根于机械方面,参加过各种大小型机器人赛事,ROBOCON,ROBOMASTER,挑战者杯,电子设计大赛,带队参加RM,物流小车,机械创新大赛等小型赛事项目。机械专业方面,本人投入了较大量时间,机械设计软件包括Solidworks,Creo,Preo均熟练掌握并完成多个设计项目,后投入于CAE仿真领域,主要以Ansys软件为主,从workbench入手,到Ansys APDL,到Hypermesh前处理操作,掌握结构静力学分析,瞬态动力学,刚体动力学,模态,谐响应,屈曲,疲劳,稳态热,瞬态热,热力耦合,刚柔耦合,等场间耦合状态的分析,还有一些焊接,切削等领域的有限元分析,并获得专业课程培训,掌握并应用于多个中小型项目中。在机械行业有所感悟也有所挣扎,在电子领域中也有自己微薄的见解,一些对前路感到迷茫的同学可以评论询问我,我最近一年也会慢慢的分享我在机械和电子包括机器人方面的一些技术知识和能力。
当然如果对我或者我的经历感兴趣的人较多的话,也可以建个群,方便大家了解和学习。
mian.c
#include "delay.h"
#include "usart.h"
#include "motor.h"
#include "ultrasonsic.h"
#include <stdio.h>
int main(void)
{
float Length = 0;
float k = 0;
delay_init(); //延迟函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组设置
uart_init(115200); //串口初始化设置
TIM5_PWM_Init(450,7199); //PWM输出初始化
uart_init(9600);
TIM3_Int_Init();
while(1)
{
//设置通道2的占空比实现PWM调速,这里是100,在0~450间,越小速度越快
Length = Senor_Using();
k = Length/17.333-1.154;
TIM_SetCompare3(TIM5,k);
P5_HIGH;
P4_LOW;
delay_ms(50);
// if(Length > 1000)
// {
// TIM_SetCompare3(TIM5,200);
// P5_HIGH;
// P4_LOW;
// delay_ms(50);
// }
// else if (Length < 1000)
// {
// P5_LOW;
// P4_LOW;
// delay_ms(50);
// }
printf("%.3f\r\n",k);
delay_ms(50);
}
}
使用TIM5定时器,对PA2输出PWM信号
motor.c
#include "motor.h"
#include "usart.h"
//TIM3 PWM部分初始化
//PWM输出初始化
//arr:自动重装载值
//psc 时钟预分频系数
void TIM5_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIO外设时钟
//初始化IOPA4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
//初始化IOPA5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
//初始化IOPA2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//初始化TIM5
TIM_TimeBaseStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
//初始化TIM5 Channel3
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择PWM模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low ; //输出比较极性地
TIM_OC3Init(TIM5, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable); //使能定时器5通道2预装载寄存器
TIM_Cmd(TIM5, ENABLE); //使能TIM5
}
motor.h
#ifndef __MOTOR_H
#define __MOTOR_H
#include "sys.h"
#define P4 GPIO_Pin_4
#define P5 GPIO_Pin_5
//#define MORTOR_PROT GPIOA
#define P4_LOW GPIO_ResetBits(GPIOA,P4)
#define P4_HIGH GPIO_SetBits(GPIOA,P4)
#define P5_LOW GPIO_ResetBits(GPIOA,P5)
#define P5_HIGH GPIO_SetBits(GPIOA,P5)
void TIM5_PWM_Init(u16 arr,u16 psc);
#endif
超声波传感器的C文件。使用TIM3定时器进行操作,
ultrasonsic.c
#include "usart.h"
#include "delay.h"
#include "ultrasonsic.h"
#include "stm32f10x.h"
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
unsigned overcount=0;//记录定时器溢出次数
void TIM3_Int_Init()
{
GPIO_InitTypeDef GPIO_InitStruct; //定义结构体函数
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //PA6设置推挽输出
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//设置PA7
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = 99; //设置重装载值为999
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIM3时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, DISABLE); //使能TIMx
}
//测距函数
float Senor_Using(void)//单精度数据类型
{
float length=0,sum=0;
u16 tim;
unsigned int i=0;
/*测五次数据计算一次平均值*/
while(i!=5)
{
PAout(6)=1;//拉高信号,作为触发信号
delay_us(20);//高电平信号超过10us
PAout(6)=0;//等待回响信号
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)==RESET);
TIM_Cmd(TIM3,ENABLE);//回响信号到来,开启定时器计数
i+=1;//每收到一次回响信号+1,收到5次就计算均值
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)==SET);//回响信号消失
TIM_Cmd(TIM3,DISABLE);//关闭定时器
tim=TIM_GetCounter(TIM3);//获取计TIM3数寄存器中的计数值
length=(tim+overcount*1000)/58.0;//通过回响信号计算距离
sum=length+sum;
TIM3->CNT=0;//将TIM2计数寄存器的计数值清零
overcount=0;//中断溢出次数清零
delay_ms(100);
}
length=sum/5;//距离作为函数返回值
return length;
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3,TIM_IT_Update)!= RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
overcount++;
}
}
ultrasonsic.h
#ifndef __ultrasonsic_H
#define __ultrasonsic_H
#include "sys.h"
#define TRIG_Send PAout(6)//输出端口为PA6
#define ECHO_Reci PAin(7)//输入端口为PA5
float Senor_Using(void);
void TIM3_Int_Init();
#endif