PCA9685 16路PWM 控制板 STM32F103 驱动

PCA9685 拥有16路PWM,通过 IIC 与 STM32 进行通信,以下驱动代码已通过测试,你可以进行更多代码优化

#include "pca9685.h"// 向 PCA9685 写入一个字节数据
static void PCA9685_write8( uint8_t addr, uint8_t d) {while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));  // 等待总线空闲I2C_GenerateSTART(I2C2, ENABLE);  // 产生起始信号while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));  // 等待起始信号发送完成I2C_Send7bitAddress(I2C2, PCA9685_ADRESS << 1, I2C_Direction_Transmitter);  // 发送从机地址while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  // 等待地址发送完成I2C_SendData(I2C2, addr);  // 发送寄存器地址while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));  // 等待寄存器地址发送完成I2C_SendData(I2C2, d);  // 发送数据while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));  // 等待数据发送完成I2C_GenerateSTOP(I2C2, ENABLE);  // 产生停止信号delay_ms(1);  // 延时一段时间
}// 从 PCA9685 读取一个字节数据
static uint8_t PCA9685_read8( uint8_t addr) {uint8_t data;while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));  // 等待总线空闲I2C_GenerateSTART(I2C2, ENABLE);  // 产生起始信号while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));  // 等待起始信号发送完成I2C_Send7bitAddress(I2C2, PCA9685_ADRESS << 1, I2C_Direction_Transmitter);  // 发送从机地址while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  // 等待地址发送完成I2C_SendData(I2C2, addr);  // 发送寄存器地址while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));  // 等待寄存器地址发送完成I2C_GenerateSTART(I2C2, ENABLE);  // 再次产生起始信号while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));  // 等待起始信号发送完成I2C_Send7bitAddress(I2C2, PCA9685_ADRESS << 1 | 0x01, I2C_Direction_Receiver);  // 发送从机地址(读模式)while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));  // 等待地址发送完成I2C_AcknowledgeConfig(I2C2, DISABLE);  // 关闭应答I2C_GenerateSTOP(I2C2, ENABLE);  // 产生停止信号while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));  // 等待数据接收完成data = I2C_ReceiveData(I2C2);  // 读取数据return data;
}// 初始化 PCA9685 结构体
void PCA9685_Init() {GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef I2C_InitStructure;// 使能 I2C2 和 GPIOB 时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 配置 I2C2 引脚(PB10 - SCL, PB11 - SDA)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);// 配置 I2C2I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 = 0x00;I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 100000;I2C_Init(I2C2, &I2C_InitStructure);// 使能 I2C2I2C_Cmd(I2C2, ENABLE);delay_ms(5);PCA9685_begin();
}// 开始使用 PCA9685
void PCA9685_begin() {PCA9685_reset();
}// 复位 PCA9685
void PCA9685_reset() {PCA9685_write8(PCA9685_MODE1, 0x0);
}// 设置 PWM 频率
void PCA9685_setPWMFreq( float freq) {freq *= 0.9;  // 校正频率设置中的过冲float prescaleval = 25000000;prescaleval /= 4096;prescaleval /= freq;prescaleval -= 1;uint8_t prescale = (uint8_t)floor(prescaleval + 0.5);uint8_t oldmode = PCA9685_read8( PCA9685_MODE1);uint8_t newmode = (oldmode & 0x7F) | 0x10; // 进入睡眠模式PCA9685_write8( PCA9685_MODE1, newmode); // 进入睡眠模式PCA9685_write8( PCA9685_PRESCALE, prescale); // 设置预分频器PCA9685_write8( PCA9685_MODE1, oldmode);delay_ms(5);PCA9685_write8( PCA9685_MODE1, oldmode | 0xa1);  // 开启自动递增模式
}// 设置单个通道的 PWM 值  4095
void PCA9685_setPWM( uint8_t num, uint16_t on, uint16_t off) {PCA9685_write8( LED0_ON_L + 4 * num, on & 0xFF);PCA9685_write8( LED0_ON_H + 4 * num, on >> 8);PCA9685_write8( LED0_OFF_L + 4 * num, off & 0xFF);PCA9685_write8( LED0_OFF_H + 4 * num, off >> 8);
}// 工具函数,根据占空比设置 PWM
// channel: 0- 15     dutyCycle:0-1.0
void setPCA9685PWMWithDutyCycle(uint8_t channel, float dutyCycle) {// 检查占空比是否在有效范围内if (dutyCycle < 0.0) {dutyCycle = 0.0;} else if (dutyCycle > 1.0) {dutyCycle = 1.0;}// PCA9685 的 PWM 分辨率是 12 位,最大值为 4095const uint16_t pwmMax = 4095;uint16_t offValue = (uint16_t)(dutyCycle * pwmMax);// 调用 PCA9685_setPWM 函数设置 PWMPCA9685_setPWM(channel, 0, offValue);
}// 设置引脚的 PWM 值
void PCA9685_setPin( uint8_t num, uint16_t val, uint8_t invert) {// 限制值在 0 到 4095 之间if (val > 4095) val = 4095;if (invert) {if (val == 0) {// 信号全高的特殊值PCA9685_setPWM(num, 4096, 0);} else if (val == 4095) {// 信号全低的特殊值PCA9685_setPWM( num, 0, 4096);} else {PCA9685_setPWM( num, 0, 4095 - val);}} else {if (val == 4095) {// 信号全高的特殊值PCA9685_setPWM( num, 4096, 0);} else if (val == 0) {// 信号全低的特殊值PCA9685_setPWM(num, 0, 4096);} else {PCA9685_setPWM(num, 0, val);}}
}
#ifndef PCA9685_H
#define PCA9685_H
#include "stm32f10x.h"
#include <math.h>
#include "delay.h"// PCA9685 寄存器地址
#define PCA9685_SUBADR1 0x2
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4#define PCA9685_ADRESS 0x40#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_Init(void);
void PCA9685_begin(void);
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, uint8_t invert);
void setPCA9685PWMWithDutyCycle(uint8_t channel, float dutyCycle);
#endif

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

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

相关文章

使用 Apache Spark 进行大数据分析

使用 Apache Spark 进行大数据分析 环境准备 为了能够在本地环境中运行Spark程序&#xff0c;需要先完成环境搭建。确保已经安装了Jupyter Notebook和Apache Spark&#xff0c;并完成了两者之间的集成。 创建 SparkSession 在 Python 中使用 PySpark 时&#xff0c;通常会创…

2025 专业的物联网软件开发公司有哪些

物联网&#xff08;Internet of Things&#xff0c;简称IoT&#xff09;具有多个显著的优势&#xff0c;主要包括提高效率、节省成本、数据收集与分析、自动化控制、改善用户体验、增强决策能力和创新业务模式‌。2025&#xff0c;有哪些比较专业的物联网开发公司呢&#xff1f…

7.PPT:“中国梦”学习实践活动【20】

目录 NO1234​ NO5678​ NO9\10\11 NO1234 考生文件夹下创建一个名为“PPT.pptx”的新演示文稿Word素材文档的文字&#xff1a;复制/挪动→“PPT.pptx”的新演示文稿&#xff08;蓝色、黑色、红色&#xff09; 视图→幻灯片母版→重命名&#xff1a;“中国梦母版1”→背景样…

学习笔记十九:K8S生成pod过程

K8S生成pod过程 流程图具体生成过程用户提交 Pod 定义API Server 处理请求调度器分配节点&#xff08;Scheduling&#xff09;目标节点上的 Pod 创建网络配置状态上报与监控控制器管理&#xff08;Controller Manager&#xff09;就绪与服务发现 关键错误场景高级特性 流程图 具…

封装descriptions组件,描述,灵活

效果 1、组件1&#xff0c;dade-descriptions.vue <template><table><tbody><slot></slot></tbody> </table> </template><script> </script><style scoped>table {width: 100%;border-collapse: coll…

21.2.6 字体和边框

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 通过设置Rang.Font对象的几个成员就可以修改字体&#xff0c;设置Range.Borders就可以修改边框样式。 【例 21.6】【项目&#xff…

FPGA VGA timing

概念 VGA(Video Graphics Array)时序是控制VGA接口显示图像的关键参数,它主要包括行时序和场时序两部分。以下是对VGA时序的详细解释: 一、VGA接口简介 VGA接口是IBM公司在1987年推出的一种使用模拟信号的视频传输标准,具有成本低、结构简单、应用灵活等优点,至今仍被广…

中级通信工程师综合教材(5、6章节)

五、现代通信网 1、通信网的构成要素 通信网在硬件设备方面的构成要素是交换设备、传输链路和终设备。 构成要素 功能作用 常见设备举例 终端设备 通信的源点和目的地 电话机、传真机、计算机、视频终端、多媒体终端等 交换设备 通信网的核心设备,主要完成呼叫处理、信令处理…

360手机刷机 360手机解Bootloader 360手机ROOT

360手机刷机 360手机解Bootloader 360手机ROOT 问&#xff1a;360手机已停产&#xff0c;现在和以后&#xff0c;能刷机吗&#xff1f; 答&#xff1a;360手机&#xff0c;是肯定能刷机的 360手机资源下载网站 360手机-360手机刷机RootTwrp 360os.top 360rom.github.io 一、…

.net一些知识点5

1.dot Net带out的参数如何使用 string name;//假设这个参数带out TestMethod(1,out name);//一定要有out 方法体中&#xff0c;一定要有out参数的赋值&#xff0c;并且能输出 2.参数的传递方式有哪些 a.值传递 b.引用传递 ref c.输出传递 out 3.设计模式知道哪些 3.us…

链表专题-02

链表专题 /*** 链表的节点* param <E>*/ public class ListNode<E> {public E element;public ListNode<E> next;public ListNode() {}public ListNode(E element) {this.element element;}public ListNode(E element, ListNode<E> next) {this.eleme…

外部中断实验 #STM32F407

外部中断实验 此实验将外部中断配置为按键输入&#xff0c;通过按键输入触发外部中断&#xff0c;在外部中断里面实施相应的处理&#xff0c;具体功能&#xff1a; 按下KEY0&#xff0c;翻转LED0状态按下KEY1&#xff0c;翻转LED1状态按下KEY2&#xff0c;同时翻转LED0和LED1…

java中如何给内部类的属性赋值

在 Java 中&#xff0c;内部类的属性赋值方式取决于该属性的访问修饰符、内部类的类型&#xff08;非静态或静态&#xff09;&#xff0c;以及赋值的时机。以下是几种常见的方式&#xff1a; 1. 通过构造方法赋值 class Outer {class Inner {private String name;// 构造方法赋…

机器学习8-卷积和卷积核1

机器学习8-卷积和卷积核1 卷积与图像去噪卷积的定义与性质定义性质卷积的原理卷积步骤卷积的示例与应用卷积的优缺点优点缺点 总结 高斯卷积核卷积核尺寸的设置依据任务类型考虑数据特性实验与调优 高斯函数标准差的设置依据平滑需求结合卷积核尺寸实际应用场景 总结 图像噪声与…

SVN 提交与原有文件类型不一样的文件时的操作

SVN 提交与原有文件类型不一样的文件时的操作 背景 SVN 服务器上原本的文件是软链接类型的&#xff0c;但是我将它改成普通文件再上传。出现了以下提示&#xff1a; 解决过程 本来想着通过 svn rm 和 svn add 来解决&#xff0c;但是行不通。 最终解决方案 svn rm --keep-…

阿里云专有云网络架构学习

阿里云专有云网络架构 叶脊&#xff08;spine-leaf&#xff09;网络和传统三层网络拓扑对比 阿里云网络架构V3拓扑角色介绍推荐设备设备组网举例带外管理网络带外网和带内网对比设备介绍 安全网络设备介绍 参考 后续更新流量分析叶脊&#xff08;spine-leaf&#xff09;网络和传…

Deepseek本地部署指南:在linux服务器部署,在mac远程web-ui访问

1. 在Linux服务器上部署DeepSeek模型 要在 Linux 上通过 Ollama 安装和使用模型&#xff0c;您可以按照以下步骤进行操作&#xff1a; 步骤 1&#xff1a;安装 Ollama 安装 Ollama&#xff1a; 使用以下命令安装 Ollama&#xff1a; curl -sSfL https://ollama.com/download.…

3D数字化营销:重塑家居电商新生态

随着电商的蓬勃发展&#xff0c;网上订购家具已成为众多消费者的首选。然而&#xff0c;线上选购家具的诸多挑战&#xff0c;如风格不匹配、尺寸不合适、定制效果不如预期以及退换货不便等&#xff0c;一直困扰着消费者。为解决这些问题&#xff0c;家居行业急需一种全新的展示…

重塑“景区+商业”模式,打造特色文旅新体验

重塑“景区商业”模式&#xff0c;打造特色文旅新体验 近年来&#xff0c;旅游业蓬勃发展&#xff0c;旅游热潮不断升温&#xff0c;游客消费观念也随之升级。为顺应这一趋势&#xff0c;各大景区纷纷探索打造特色文旅项目&#xff0c;以期吸引更多游客。然而&#xff0c;“景…

在亚马逊云科技上云原生部署DeepSeek-R1模型(下)

在本系列的上篇中&#xff0c;我们介绍了如何通过Amazon Bedrock部署并测试使用了DeepSeek模型。在接下来的下篇中小李哥将继续介绍&#xff0c;如何利用亚马逊的AI模型训练平台SageMaker AI中的&#xff0c;Amazon Sagemaker JumpStart通过脚本轻松一键式部署DeepSeek预训练模…