STM32F103控制PCA9685产生16路PWM波控制SG90舵机

2023-05-16

STM32控制PCA9685产生16路PWM波控制SG90舵机

如果你能点开这篇文章,说明你已经知道PCA9685是多么强大,NXP公司原本做这片芯片是为了提供给LED使用,在其官方文档里也能看到所有PWM输出都是写着LED,但是PWM波形不仅仅能够控制一个简单的LED,PWM应用很广泛的一个方面就是电机调速,以及部分舵机控制角度就是通过调节PWM波的占空比来实现,因此本篇博客就来介绍一下这块如何使用这块芯片。

博主采用的是下面这款模块,淘宝上很容易买到。

PCA9685模块·

这款芯片通过IIC总线来控制,如果你想很快上手,可以参考博主的另一篇文章通用软件模拟IIC,只需要改改你要用的引脚就可以了。

闲话少说,上代码

芯片使用可以参考这篇文章,我这里只讲怎么用

#ifndef _PCA9685_H
#define _PCA9685_H

#include "sys.h"
#include "delay.h"
#include "iic.h"

// 这里是你PWM模块的IIC地址,默认是0x80,你需要修改为你使用的地址
#define pca_adrr 0x80
// 芯片工作模式
#define pca_mode1 0x00
// 设置芯片分频
#define pca_pre 0xFE
// 通道地址
#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09
 
 
//#define jdMIN  115 // minimum
//#define jdMAX  590 // maximum
//#define jd000  130 //0度对应4096的脉宽计数值
//#define jd180  520 //180度对应4096的脉宽计算值

void pca_write(u8 adrr,u8 data);
u8 pca_read(u8 adrr);
void PCA9685_Init(float hz,u8 angle);
void pca_setfreq(float freq);
void pca_setpwm(u8 num, u32 on, u32 off);
void PCA_Set(u8 num,u8 start_angle,u8 end_angle,u8 mode,u8 speed);

#endif

下面是具体实现的代码

#include "pca9685.h"
#include "iic.h"
#include "delay.h"
#include "math.h"

// 向PCA写数据,adrrd地址,data数据
void pca_write(u8 adrr,u8 data)
{ 
	IIC_Start();
	
	IIC_Write_One_Byte(pca_adrr);
	IIC_Wait_Ack();
	
	IIC_Write_One_Byte(adrr);
	IIC_Wait_Ack();
	
	IIC_Write_One_Byte(data);
	IIC_Wait_Ack();
	
	IIC_Stop();
}

//从PCA读数据
u8 pca_read(u8 adrr)
{
	u8 data;
	IIC_Start();
	
	IIC_Write_One_Byte(pca_adrr);
	IIC_Wait_Ack();
	
	IIC_Write_One_Byte(adrr);
	IIC_Wait_Ack();
	
	IIC_Start();
	
	IIC_Write_One_Byte(pca_adrr|0x01);
	IIC_Wait_Ack();
	
	data=IIC_Read_One_Byte(0);
	IIC_Stop();
	
	return data;
}

//设置PWM频率
void pca_setfreq(float freq)
{
		u8 prescale,oldmode,newmode;
		double prescaleval;
    	// 这里的计算看不懂的话可以去前面看看提到的那篇文章 
		freq *= 0.915; 
		prescaleval = 25000000;
		prescaleval /= 4096;
		prescaleval /= freq;
		prescaleval -= 1;
		prescale =floor(prescaleval + 0.5f);

		oldmode = pca_read(pca_mode1);
	
		newmode = (oldmode&0x7F) | 0x10; // sleep
	
		pca_write(pca_mode1, newmode); // 设置时钟前必须先进入sleep模式
	
		pca_write(pca_pre, prescale); // 设置分频
	
		pca_write(pca_mode1, oldmode); // 写入原先模式
		delay_ms(2);
	
		pca_write(pca_mode1, oldmode | 0xa1); 
}
// 设定通道的PWM
void pca_setpwm(u8 num, u32 on, u32 off)
{
		pca_write(LED0_ON_L+4*num,on);
		pca_write(LED0_ON_H+4*num,on>>8);
		pca_write(LED0_OFF_L+4*num,off);
		pca_write(LED0_OFF_H+4*num,off>>8);
}
/**
 *@num:舵机PWM输出引脚0~15
 *@on:PWM上升计数值0~4096
 *@off:PWM下降计数值0~4096
 *一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,off/4096的值就是PWM的占空比。
**/

/*
	函数作用:初始化舵机驱动板
	参数:1.PWM频率
		  2.初始化舵机角度
*/
void PCA9685_Init(float hz,u8 angle)
{
	u32 off=0;
    u8 i=0;
	IIC_Init();
	pca_write(pca_mode1,0x0);
	pca_setfreq(hz);//设置PWM频率
	off=(u32)(102+angle*2.2);
    // 初始化所有通道固定为指定的角度angle
	for(i=0;i<=15;i++)
    {
        pca_setpwm(i,0,off);
    }
	
	delay_ms(500);
}

/*
	函数作用:控制舵机转动;
	参数:1.输出端口,可选0~15;
		  2.起始角度,可选0~180;
		  3.结束角度,可选0~180;
		  4.模式选择,0 表示函数内无延时,调用时需要在函数后另外加延时函数,且不可调速,第五个参数可填任意值;
					  1 表示函数内有延时,调用时不需要在函数后另外加延时函数,且不可调速,第五个参数可填任意值;
					  2 表示速度可调,第五个参数表示速度值;
		  5.速度,可填大于 0 的任意值,填 1 时速度最快,数值越大,速度越小;
	注意事项:模式 0和1 的速度比模式 2 的最大速度大;
*/
// 一般使用的话mode选0就可以了,此时start_angle也可以写0,以及speed,只有end_angle是你要输出的角度。
void PCA_Set(u8 num,u8 start_angle,u8 end_angle,u8 mode,u8 speed)
{
	u8 i;
	u32 off=0;
	switch(mode)
	{
		case 0:
		{
			off=(u32)(102+end_angle*2.2);
			pca_setpwm(num,0,off);
		}break;

		case 1:
		{
			off=(u32)(158+end_angle*2.2);
			pca_setpwm(num,0,off);
			if(end_angle>start_angle)
            {
                delay_ms((u16)((end_angle-start_angle)*2.7));  // 若要使用模式1或者2,可以调整这里的倍数2.7为你需要的
            }
			else
            {
                delay_ms((u16)((start_angle-end_angle)*2.7));
            }
		}break;
		case 2:
		{
			if(end_angle>start_angle)
			{
				for(i=start_angle;i<=end_angle;i++)
				{
					off=(u32)(158+i*2.2);
					pca_setpwm(num,0,off);
					delay_ms(2);
					delay_us(speed*250);
				}
			}
			else if(start_angle>end_angle)
			{
				for(i=start_angle;i>=end_angle;i--)
				{
					off=(u32)(158+i*2.2);
					pca_setpwm(num,0,off);
					delay_ms(2);
					delay_us(speed*250);
				}
			}
		}break;
	}
}

代码中使用到的delay和sys,以及iic可以通过另外一篇文章页尾下载,这里就不放链接了。

经测试可以看到舵机的输出角度比较稳定。

这里还是简单说一下舵机SG90吧,这是一款90g舵机,通过周期为50Hz的PWM波控制,也就是20ms,其中0.5ms高电平时舵机输出0度,1ms输出45度,1.5ms输出90度,2ms输出135度,2.5ms输出180度,在代码中通过off=(u32)(158+i*2.2);来将其转变成具体要写到芯片通道寄存器的值,你可以通过调整这个计算式来调整精度,不过经博主个人测试,输出精度已经足够,能够满足一般使用了。

觉得有用不妨点个赞吧,欢迎点击这里访问博主个人网站,一起交流学习

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103控制PCA9685产生16路PWM波控制SG90舵机 的相关文章

  • PWM波控制舵机总结

    文章转载自 https www cnblogs com zhoubatuo p 6138033 html 一 关于舵机 xff1a 舵机 xff08 英文叫Servo xff09 xff1a 它由直流电机 减速齿轮组 传感器和控制电路组成的
  • 首个单芯片超小封装I2C转PWM解决方案

    ZW10I8X系列 高性能工业级16位高精度I2C转PWM接口SOC芯片 接口标准 符合飞利浦的I2C标准规范 xff0c 目前支持的速度为小于100kbit 建议使用50k 1个使能脚 xff08 ZW10I8xE后缀带E的 xff09
  • STM32CUBEMX使用PWM+DMA驱动WS2812

    STM32CUBEMX使用PWM 43 DMA驱动WS2812 首先在stm32cubemx中设置pwm和dma 我设置了TIM1的CH1为PWM引脚编写DMA响应函数 xff0c 即PWM DMA完成数据发送后的回调函数 PWM DMA
  • STM32Cube的PWM控制基础篇(一)一路PWM设置

    以下是有关STM32cube的PWM的花式操作 xff0c 大佬们在看下面链接之前建议先看完本博客 xff0c 个人觉得写的比较详细 xff0c 欢迎大佬之指正 xff01 STM32Cube的PWM控制基础篇 xff08 二 xff09
  • (3)STM32 SG90舵机模块测试

    文章目录 1 资源简介2 测试源码 1 资源简介 stm32 rct6板SG90舵机模块 接线引脚 xff1a 橙色 xff1a 信号线 红色 xff1a 电源 43 5v 咖色 xff1a GND 此模块三条线固定在一起 xff0c 如果
  • RT-Thread Stm32f103开启UART2(中断接收及轮询发送) 使用RT-Thread Studio

    RT Thread Stm32f103开启UART2 使用RT Thread Studio 1 使用RT Thread Studio新建RT Thread项目 2 修改dricer gt doard h 增加UART2的宏定义设置gpio接
  • stm32高级定时器实现pwm互补输出

    简介 stm32设备一般都有很多类型的定时器 xff0c 常见的有systick timer 基本定时器 通用定时器 高级定时器 看门狗定时器 RTC等等 xff0c 本文简单介绍高级定时器是如何实现pwm互补输出 详细 我这里使用的dev
  • 怎么把PWM信号转为模拟量

    有一个测量位置变化的位置传感器 xff0c 用万用表电压档测量传感器的输出信号 xff0c 结果显示的是模拟量信号 xff0c 即位置和信号输出大小呈线性关系 但是 xff0c 用示波器 xff08 Picoscope 4227 xff09
  • 舵机PWM信号转互斥继电器开关信号

    本文由 麦粒电子 撰写 xff0c 并提供相应产品服务 叙述 上次的PWM转继电器开关方案得到大家的不少好评 xff08 博客链接 xff09 xff0c 但是发现有些玩家需要一路PWM同时去控制两路继电器开关通断 xff0c 并且两者是互
  • IMX6ULL与STM32F103的CAN通信实现

    IMX6ULL与STM32F103的CAN通信实现 硬件连接驱动层实现IMX6ULLSTM32F103ZET6 应用层实现IMX6ULLSTM32F103ZET6 结果 在上一篇博文中 xff0c 我们利用USBCAN设备及其上位机软件 x
  • 使用STM32F103做CAN的收发通信

    下面也是搭建嵌入式系统所必须的一个部分 参考网站 xff1a https www cnblogs com craigtao p 3645148 html https blog csdn net qq 29413829 article det
  • 学习PS2无线手柄解码通讯手册

    学习 PS2 无线手柄的使用方法 将市场上 PS2 手柄通过解码应用到我们自己产品之中 比如控制智能车 机械臂等等任何涉及无线通信控制的一些diy场景 本次主要让大家了解 PS2 无线手柄的工作原理 以及掌握 PS2 无线手柄的使用并最终通
  • 直流电机控制 pwm 和 pid 算法

    下面的文章是我转载的 所以作者若是看到不允许转载 请给我留言或给我邮件 lushiliangcsdn 163 com 我会立即删除 转载原因 这篇文章把pid 算法解释的很详细 我担心以后这篇文章无故删除 才转载到我这边的 谢谢 转载来源于
  • 入门stm32简单电灯实验

    看原理图找内置LED接线 stm32f103 我这边是接的 PE5 外设时钟使能寄存器的相关配置 因为LED1接的是PE5 所以GBIO端口E 查看中文手册获取GPIOE寄存器起始地址0x4001 1800 通过查看系统架构 可以发现GPI
  • STM32F103 UART4串口使用DMA接收不定长数据和DMA中断发送

    一 前言 使用DMA通信的好处是 不占用单片机资源 不像普通串口中断 发送一个字节触发一次中断 发送100个字节触发100次中断 接收一个字节触发一次中断 接收200个字节触发200次中断 数据接收完毕触发一次DMA中断 发送数据完毕触发一
  • 基于STM32F103 实现按键状态机

    文章目录 开发板 开发环境 前言 按键消抖 按键硬件原理图 软件延时实现思路 实验目的 代码 按键状态 按键信息 按键相关定义 按键底层配置及状态获取 总结 开发板 正点原子STM32F103ZET6战舰 开发环境 stm32cubeMX
  • 使用HAL库开发STM32:使用Timer输出PWM信号

    文章目录 目的 基础说明 输出PWM信号 总结 目的 单片机输出PWM信号是很常用的一种功能需求 STM32中通常使用Timer来输出PWM信号 这篇文章将对相关内容做个说明 基础说明 在使用Timer输出PWM信号需要了解一些Timer的
  • 什么是死区时间

    死区时间是PWM输出时 为了使H桥或半H桥的上下管不会因为开关的关断延迟问题发生同时导通而设置的一个保护时段 通常也指pwm响应时间 由于IGBT 绝缘栅极型功率管 等功率器件都存在一定的结电容 所以会造成器件导通关断的延迟现象 一般在设计
  • 快速学习Stm32舵机控制板控制多个舵机运动以及调速

    本次分享stm32对多个舵机的控制 之前讲解过单个舵机的控制 以及控制原理 定时器的使用和pwm的输出来控制一个舵机的角度转向 这次就和大家分享一下多个舵机的控制以及调速 利用单片机实现对 8 个舵机的同时控制 掌握多个舵机控制程序实现方法
  • 一起学nRF51xx 9 -  pwm

    前言 上一讲我们学习了nrf51822定的器的使用 那行如何用定时器实现PWM输出呢 NRF51的time模块不支持 PWM 功能 不可我们可以通过定时器 PPI GPIOTE模块一起工作的方式在NRF51XX上产生 PWM 信号 下面以使

随机推荐

  • Java基础篇:Iterator迭代器

    一 什么是Iterator xff1a 迭代器 Iterator 是一个对象 xff0c 它的工作是遍历并目标序列中的对象 xff0c 它提供了一种访问一个容器 container 对象中的各个元素的方法 xff0c 把访问逻辑从不同类型的
  • 2022-2-19 ros环境变量

    学习时间及标题 xff1a 2022 2 19 ros环境变量 学习内容 xff1a 1 添加环境变量 xff1a source span class token operator span span class token operato
  • EGO-Planner: An ESDF-free Gradient-based Local Planner for Quadrotors(论文学习)

    EGO规划器 xff1a 一种基于ESDF自由梯度的四转子局部规划器 摘要 ESDF地图被广泛运用在局部地图的梯度方向和大小估计之中 xff0c 但是由于我们在进行轨迹优化的过程中 xff0c 只用到了ESDF地图中很小的一部分 xff0c
  • cmake "undefined reference to"

    main函数在调用其他 c或 cpp文件的函数时 xff0c 有以下几种情况 函数名写错 没有将其他 c或 cpp文件链接到main o xff0c 导致main函数在执行时找不到需要调用的函数 的解决方法 修改CMakeLists txt
  • STM32串口详解

    实验一 xff1a 简单的利用串口接收中断回调函数实现数据的返回 关于串口调试助手 xff0c 还应知道 xff1a 发送英文字符需要用一个字符即8位 xff0c 发送汉字需要两个字符即16位 xff0c 如上图 xff0c 发送汉字 姜
  • RLException: [xx.launch] is neither a launch file in package [x] nor is [x] a launch file name的解决方法

    ROS学习过程中 xff0c 遇到问题 xff1a RLException xx launch is neither a launch file in package x nor is x a launch file name 出现的问题
  • numpy 中 shape 与 size 属性

    因为需要生成一个和现有矩阵大小相等的矩阵 xff0c 故查找了相关资料 span class token operator gt gt span span class token operator gt span span class to
  • Ubtuntu+C语言实现网络通信附源代码

    下面这个案例是我用C在ubtuntu上面写的网络编程案例 2 网络编程 xff08 1 xff09 OSI七层模型理想化 应用层 xff1a app xff0c 应用程序 表示层 xff1a 对数据进行加工 会话层 xff1a 建立会话 x
  • Jetson Nano的GPIO口学习

    1 配置GPIO库 https github com NVIDIA jetson gpio 1 安装pip工具 sudo apt get update sudo apt get install python3 pip sudo apt ge
  • 22.11.22 TCP与UDP 客户端与服务器 协议搭建

    ubuntu 64 ubuntu yuyu yu 11 cat Tcp Cli c 客户端 include lt stdio h gt include lt sys types h gt include lt sys socket h gt
  • cmake交叉编译配置

    cmake交叉编译配置 很多时候 xff0c 我们在开发的时候是面对嵌入式平台 xff0c 因此由于资源的限制需要用到相关的交叉编译 即在你host宿主机上要生成target目标机的程序 里面牵扯到相关头文件的切换和编译器的选择以及环境变量
  • OS——gcc、g++、gdb、vim、vs code的基本使用

    文章目录 g 43 43 的使用gdb的使用vim的使用vscode的使用vs code的安装vs code中C 43 43 的编译运行配置 如果想要学习如何在CentOS 7中安装配置gcc g 43 43 gdb zhs和oh my z
  • make和cmake

    编程人员已经使用CMake和Make很长一段时间了 当你加入一家大公司或者开始在一个具有大量代码的工程上开展工作时 xff0c 你需要注意所有的构建 你需要看到处跳转的 CMakeLists txt 文件 你应该会在终端使用 cmake 和
  • ubuntu自带python与anaconda python环境的切换

    ubuntu的python可分为三大类 xff1a 1 ubuntu自带的python环境 一般安装在 usr bin 中python2和python3可以共存 2 anaconda自带的base环境 3 在anaconda中创建的虚拟py
  • 详细介绍如何在ubuntu20.04中安装ROS系统,以及安装过程中出现的常见错误的解决方法,填坑!!!

    本篇文章写于2020 10 xff0c 经过很多小伙伴的验证 xff0c 文章所介绍的步骤是可以正常完成安装的 xff0c 现在是2021 10 xff0c 经过近期的探索 xff0c 我将安装步骤进行了进一步的优化 xff0c 使安装变得
  • VScode进行python开发出现 No module named “XXX“的解决方法

    VScode进行python开发出现 No module named 34 XXX 34 的解决方法 最近从pycharm转向vscode的时候 xff0c 遇到了如下问题 span class token keyword import s
  • CM3寄存器简介

    Cortex M3基础 寄存器组 通用目的寄存器组R0 R7 也被称为低组寄存器 xff0c 所有指令都能访问字长32位 通用目的寄存器组R8 R12 高组寄存器 32位寄存器 复位后的初始值不可预料 堆栈指针R13 CM3中共有两个堆栈指
  • 基于亚博K210开发板的学习之旅(一)

    本文参考亚博智能官方K210开源课程 五月份购买了亚博的K210开发板 xff0c 但由于课程压力就搁置了 xff0c 最近暑假得空又恰逢电赛清单里有这个 芯片 xff0c 就抽空学习一下 xff0c 特写下这些 xff0c 以作记录 按照
  • STM32标准库通用软件模拟IIC

    STM32标准库通用软件模拟IIC 继上次通用可移植的矩阵键盘之后 xff0c 便继续寻找着下一个能够拿来只需改改引脚就可以使用的通用方案 恰好最近在研究PCA9685 xff0c 这是一片能够产生最多十六路PWM信号的芯片 xff0c 通
  • STM32F103控制PCA9685产生16路PWM波控制SG90舵机

    STM32控制PCA9685产生16路PWM波控制SG90舵机 如果你能点开这篇文章 xff0c 说明你已经知道PCA9685是多么强大 xff0c NXP公司原本做这片芯片是为了提供给LED使用 xff0c 在其官方文档里也能看到所有PW