cubemx stm32 pca9685pw模块 16路PWM 可用于舵机驱动 驱动代码

news2024/11/25 23:01:05

资料

淘宝链接请点这里
淘宝资料资料:
链接:https://pan.baidu.com/s/1Kda-c7QdZdQ03FBMa0zeRA
提取码:1234

pca9685pw介绍

这个模块是 I2C 通信控制 16 路 PWM 的模块。
所有路的 频率 是统一设置的,所以每一路的频率都一样,但是每一路可以设置不同的占空比。

  1. PCA9685的分辨率是12位,即占空比控制时,0-4096对应的占空比为0-100,在控制舵机的时候,控制信号是0.5ms-2.5ms,周期 20ms,所以控制舵机角度不会有太高的分辨率,对舵机控制精度较高的地方不建议使用。
  2. PCA9685地址位和很多描述的不一样,根据芯片手册,地址位的寄存器一共 8 位,其中最高位固定是1,A0-A5这六位是用户可更改的,而其中最关键的一位是 R/W 位,这一位主要是决定了读还是写,置1时为读,置0时为写,所以我们在写程序的时候,PCA9685 的地址应把 R/W位加上,是 0x80,而不是 0x40,在写的时候,发送地址位是 0x80,在读的时候,发送的地址位是0x81。

iic地址

硬件

硬件连接

  • OE,低电平有效输出使能。
  • SDA,I2C 的 SDA 引脚。
  • SCL,I2C 的 SCL 引脚。
  • V+,接入 5V 电源,若是驱动的 16 路全是舵机,这个电源的电流就要求很大了(不晓得这个模块到底能不能承受这么多舵机的电流)。
  • VCC,单片机 3V3 电源。
  • GND,对于 V+ 的地平面。

原理图截屏如下:
pca9685pw模块原理图

软件编写

pca9685pw.c

#include "pca9685pw.h"
#include <math.h>
#include <stdio.h>

#define min(_X_, _Y_)	(_X_>=_Y_?_Y_:_X_)

static uint8_t read16(uint8_t addr);
static void write16(uint8_t addr, uint8_t d);


// 设置为true可打印一些调试消息,设置为false可禁用这些消息。
#define ENABLE_DEBUG_OUTPUT false

// 初始化。频率,转动角度(0~360)
void pca9685_init(float hz, uint16_t angle)
{
	uint32_t off = 0;
	// 这一步很关键,如果没有这一步PCA9685就不会正常工作。
	pca9685_reset();
	
	write16(PCA9685_MODE1,0x00);
	pca9685_setPWMFreq(hz);
	off = (uint32_t)(102.4+angle*1.14);
	
	pca9685_setPWM(0,0,off);
	pca9685_setPWM(1,0,off);
	pca9685_setPWM(2,0,off);
	pca9685_setPWM(3,0,off);
	pca9685_setPWM(4,0,off);
	pca9685_setPWM(5,0,off);
	pca9685_setPWM(6,0,off);
	pca9685_setPWM(7,0,off);
	pca9685_setPWM(8,0,off);
	pca9685_setPWM(9,0,off);
	pca9685_setPWM(10,0,off);
	pca9685_setPWM(11,0,off);
	pca9685_setPWM(12,0,off);
	pca9685_setPWM(13,0,off);
	pca9685_setPWM(14,0,off);
	pca9685_setPWM(15,0,off);
	
	HAL_Delay(100);
}

// 软件复位
void pca9685_reset(void)
{
	write16(PCA9685_MODE1, 0x0);
}

// 设置PCA9685的输出频率,
// PCA9685的16路PWM输出频率是一致的,
// 所以是不能实现不同引脚不同频率的。
void pca9685_setPWMFreq(float freq)
{
	//printf("Attempting to set freq ");
	//printf(freq);
	// 输出周期实际是有误差的,对于20ms(50Hz)的周期来说这里乘个0.94为20ms
	// 可以用示波器观看调试
	freq *= 0.942;
	double prescaleval = 25000000;
	prescaleval /= 4096;
	prescaleval /= freq;
	prescaleval -= 1;

	if (ENABLE_DEBUG_OUTPUT)
	{
		printf("Estimated pre-scale: %f\r\n", prescaleval);
	}
	// floor()总是返回小于等于一个给定数字的最大整数。
	// 这里是四舍五入
	uint8_t prescale = floor(prescaleval + 0.5);
	
	if (ENABLE_DEBUG_OUTPUT)
	{
		printf("Final pre-scale: %d\r\n", prescale);
	}

	uint8_t oldmode = read16(PCA9685_MODE1);
	uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep
	write16(PCA9685_MODE1, newmode); // go to sleep
	write16(PCA9685_PRESCALE, prescale); // set the prescaler
	write16(PCA9685_MODE1, oldmode);
	HAL_Delay(5);
	write16(PCA9685_MODE1, oldmode | 0xa1);  //  This sets the MODE1 register to turn on auto increment.
										  // This is why the beginTransmission below was not working.
	//  printf("Mode now 0x"); printf(read16(PCA9685_MODE1), HEX);
}

// 输出PWM占空比的调节。通常on都设为0,改变off即可。
// 因为PCA9685是12位分辨率,所以off的值0~4096就代表了占空比0-100.
void pca9685_setPWM(uint8_t num, uint16_t on, uint16_t off)
{
	//printf("Setting PWM "); printf(num); printf(": "); printf(on); printf("->"); printf(off);
	uint8_t d[4] = {(on&0xFF), (on>>8), (off&0xFF), (off>>8)};
	
	HAL_I2C_Mem_Write(&PCA9685_HI2C, PCA9685_IIC_ADDR_W, (LED0_ON_L+4*num), 1, d, 4, 0xff);
}

// num:序号;angle:角度
void setAngle(uint8_t num, uint16_t angle)
{
	// 补误差
//	angle /= 2;
	uint32_t off = 0;

	// off范围是:0~4096
	// 舵机占空比范围是:0.5~2.5ms
	// 所以设置off在 102.4~512范围内
	// x/(512-102.4) = 1/360
	// 所以每一度步进值为:1.137777 约等于 1.14
	off = (uint32_t)(102.4+angle*1.14);
	pca9685_setPWM(num, 0, off);
}

static uint8_t read16(uint8_t addr)
{
	uint8_t d;
	HAL_I2C_Mem_Read(&PCA9685_HI2C, PCA9685_IIC_ADDR_R, addr, 1, &d, 1, 0xff);
	return d;
}

static void write16(uint8_t addr, uint8_t d)
{
	HAL_I2C_Mem_Write(&PCA9685_HI2C, PCA9685_IIC_ADDR_W, addr, 1, &d, 1, 0xff);
}

pca9685pw.h

#ifndef _PCA9685_PW_H
#define _PCA9685_PW_H

#include "stdbool.h"
#include "main.h"
#include "i2c.h"

// I2C 句柄,用户自己修改
#define PCA9685_HI2C	hi2c1
// I2C 地址
#define PCA9685_IIC_ADDR_W	0x80
#define PCA9685_IIC_ADDR_R	0x81


// 寄存器地址
#define PCA9685_SUBADR1 0x2
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4

#define PCA9685_MODE1 0x0
#define PCA9685_PRESCALE 0xFE

#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9

#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD



// 函数
void pca9685_reset(void);
void pca9685_setPWMFreq(float freq);
void pca9685_setPWM(uint8_t num, uint16_t on, uint16_t off);
void pca9685_setPin(uint8_t num, uint16_t val, bool invert);// =false


// 初始化。频率,转动角度(0~360)
void pca9685_init(float hz, uint16_t angle);
// num:序号;angle:角度(0~360)
void setAngle(uint8_t num,uint16_t angle);

#endif	/* _PCA9685_PW_H */

main

void main(void)
{
	uint16_t xxx = 0;
	// 初始50Hz,角度 180 度
	pca9685_init(50, 180);

	while(1)
	{
		// 设置 1 号口输出
		setAngle(1, xxx);
		xxx += 10;
		xxx>360?xxx=0:xxx;
		HAL_Delay(10);
	}
}

参考

PCA9685模块使用(Arduino和STM32)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/586100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java单元测试( Hamcrest 断言)

java单元测试( Hamcrest 断言) 单元测试特征: 1 范围狭窄 2 限于单一类或方法 3 体积小 为什么要编写单元测试&#xff1f; 为了防止错误&#xff08;很明显&#xff01;&#xff09; 而且还可以提高开发人员的生产力&#xff0c;因为单元测试&#xff1a; (1) 帮助实施——在…

网工内推 | 经验不限,国企招网工,IE认证优先,五险一金

01 一九零五&#xff08;北京&#xff09;网络科技有限公司 &#x1f537;招聘岗位&#xff1a;网络工程师 &#x1f537;职责描述&#xff1a; 1、负责公司内部现有网络配置及调优&#xff1b; 2、负责IT机房的网络和安全的日常维护工作&#xff1b; 3、负责IT机房的紧急故…

轻松掌握redis缓存穿透、击穿、雪崩问题及解决方案(20230529版)

1、缓存穿透 所谓缓存穿透就是非法传输了一个在数据库中不存在的条件&#xff0c;导致查询redis和数据库中都没有&#xff0c;并且有大量的请求进来&#xff0c;就会导致对数据库产生压力&#xff0c;解决这一问题的方法如下&#xff1a; 1、使用空缓存解决 对查询到值是空的…

【Python开发】FastAPI 02:请求参数—路径参数、查询参数

进行接口请求时&#xff0c;请求参数是重中之重了&#xff01;请求参数指客户端向服务端发送请求时&#xff0c;需要传递给服务端的参数&#xff0c;包括路径参数、查询参数、请求体等。举个例子&#xff0c;如果客户端想要获取某个用户的信息&#xff0c;可以向服务端发送一个…

PHPMySQL基础(一):创建数据库并通过PHP进行连接

PHP同样可以对数据库进行连接&#xff0c;并且实现增删改查、登录注册等功能&#xff0c;这一篇写一下怎么使用PHP去连接MySQL数据库 目录 一、创建数据库 1.1 登录页面 1.2 创建数据库 1.3 创建数据库表 1.4 添加表字段 1.5 插入数据 1.6 导出和导入 二、PHP连接数据…

华为OD机试真题B卷 Java 实现【报文重排序】,附详细解题思路

一、题目描述 对报文进行重传和重排序是常用的可靠性机制&#xff0c;重传缓冲区内有一定数量的子报文&#xff0c;每个子报文在原始报文中的顺序已知&#xff0c;现在需要恢复出原始报文。 二、输入描述 输入第一行为N&#xff0c;表示子报文的个数&#xff0c;0 < N &l…

SpringBoot 配置文件和日志文件

目录 一、SpringBoot配置文件 配置文件的格式 .properties配置文件格式 .yml配置文件格式 .properties 与 .yml的区别 配置文件的读取 .properties 与 .yml的区别 设置不同环境的配置⽂件 二、SpringBoot日志文件 日志打印的步骤 得到日志对象 方法一&#xff1a;使…

vulnhub靶场之RAGNAR LOTHBROK: 1

1.信息收集 探测存活主机&#xff0c;输入&#xff1a;netdiscover -r 192.168.239.0/24 &#xff0c;发现192.168.239.178存活。 对目标主机192.168.239.178进行端口扫描&#xff0c;发现存活21(ftp)、80、443、3306端口。 浏览器访问http://192.168.239.178&#xff0c;发…

设计模式 - 代理模式

基本介绍: 代理模式&#xff1a;为一个对象提供一个替身&#xff0c;以控制对这个对象的访问。即通过代理 对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的 功能操作,即扩展目标对象的功能。被代理的对象可以是远程对象、创建开销大的对象或需要安全控…

chatgpt赋能python:Python三次方根的用途和计算方法

Python三次方根的用途和计算方法 如果您是一位Python编程工程师&#xff0c;您可能会经常需要用到Python的数学计算功能。在这篇文章中&#xff0c;我们将探讨Python三次方根的概念和使用&#xff0c;以及如何在Python中计算三次方根。 什么是三次方根&#xff1f; 三次方根…

SpringBoot 框架

SpringBoot 框架 SpringBoot 简介SpringBoot 开发步骤SpringBoot工程快速启动SpringBoot概述起步依赖自动装配切换web服务器 配置文件配置文件格式yaml格式yaml配置文件数据读取Value注解读取配置文件Environment对象自定义对象多环境配置 SpringBoot 整合 SpringBoot 简介 Sp…

这个 计数排序详解过程 我能吹一辈子!!!

文章目录 计数排序概念计数排序算法思路计数排序算法过程计数排序代码实现计数排序缺陷 计数排序概念 计数排序是一个非基于比较的排序算法&#xff0c;元素从未排序状态变为已排序状态的过程&#xff0c;是由额外空间的辅助和元素本身的值决定的。该算法于1954年由 Harold H.…

流行框架(一)EventBus(组件通信)、ARouter(页面跳转)

文章目录 EventBus基本使用EventBus三要素五种线程模式使用步骤EventBus黏性事件&#xff08;sticky event&#xff09; 工作原理中介者模式源码解读Event Bus中介者对象register() / 注册发布事件 / post Arouter组件化开发组件化开发的优点组件分层方案组件化的gradle工程 AR…

C919商业首航 背后功臣风洞实验室有多牛

5月28日&#xff0c;国产大型客机C919&#xff0c;顺利完成商业首航。 首航背后意味着该机型从研发、制造、取证到投运全面贯通&#xff0c;广大旅客终于有机会坐国产大飞机出行了。 很多人不知道C919其实是依托我国独立自主设计制造的世界级风洞群和风洞实验室反复测试“百炼…

Linux部署jumpserver堡垒机及问题汇总

部署过程相对复杂&#xff01;请耐心浏览&#xff01; 目录 一、jumpserver堡垒机简介 1.1 为什么需要使用堡垒机? 1.2 堡垒机主要功能 二、准备工作 2.1 关闭防火墙以及SElinux 1.2 时间同步 1.3 更改主机名 1.4 yum源备份及准备 1.5 安装初始工具 1.6 修改系统字…

基于PS-InSAR技术的形变监测分析流程

基于PS-InSAR技术的形变监测分析流程 文章目录 基于PS-InSAR技术的形变监测分析流程1. 背景知识1.1 PS-InSAR技术1.1.1 雷达干涉测量1.1.2 InSAR技术1.1.3 技术原理1.1.4 技术特征1.1.5 技术优化1.1.6 应用 1.2 Sentinel-1数据1.2.1 Sentinel-1简介1.2.2 Sentinel-1扫描模式1.2…

一分钟学会怎么让chatGPT帮你写python代码(含使用地址)

一分钟学会怎么让chatGPT帮你写python代码&#xff08;含使用地址&#xff09; 我们用chatGPT做一个python的计算器脚本为例 提出需求 1、给定角色定位 2、提出要求 3、提出要求的细节 标题等待片刻&#xff0c;等待chatGPT生成脚本即可 import tkinter as tkclass Calc…

去公司面试,10:00刚进去,10:08就出来了 ,问的实在是太...

从外包出来&#xff0c;没想到算法死在另一家厂子 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到8月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内…

33 KVM管理设备-配置虚拟机PCIe控制器

文章目录 33 KVM管理设备-配置虚拟机PCIe控制器33.1 概述33.2 配置PCIe Root、PCIe Root Port和PCIe-PCI-Bridge33.2.1 简化配置方法33.2.1完整配制方法 33 KVM管理设备-配置虚拟机PCIe控制器 33.1 概述 虚拟机内部的网卡、磁盘控制器、PCIe直通设备都需要挂接到PCIe Root Po…

IOC源码解析

目录 主要从3方面进行解析 Bean与BeanDefinition 容器初始化主要做的事情(主要脉络) BeanFactory ApplicationContext 模板方法模式 Resource、ResourceLoader、容器之间的关系 BeanDefinitionReader BeanDefinition的注册 小结 主要从3方面进行解析 解析配置定位与注…