pca9685:

资料:https://blog.csdn.net/c1063891514/article/details/84401045。

#ifndef pca9685
#define pca9685#include "main.h"typedef struct
{
I2C_HandleTypeDef i2cConfig;     //不需要配置
I2C_TypeDef *i2cHardwareAddress; //I2C1
uint32_t i2cSpeed;               //100000
uint8_t pca9685Address;          //pca9865的地址,从0x40~0x7f
} pca9685ConfigStruct;void pca9685Init(pca9685ConfigStruct *pca9685ConfigStructAddress);
void pca9685ConfigPwmFreq(pca9685ConfigStruct *pca9685ConfigStructAddress, float freq);
void pca9685ConfigPwmDutyCycle(pca9685ConfigStruct *pca9685ConfigStructAddress, uint8_t number, float dutyCycle); //占空比从0~1#endif
#include "pca9685.h"static const uint8_t pca9685Mode1RegisterAddress = 0,
pca9685PrescaleRegisterAddress = 0xfe,
pca9685UpLRegisterAddress = 0x06,
pca9685UpMRegisterAddress = 0x07,
pca9685DownLRegisterAddress = 0x08,
pca9685DownMRegisterAddress = 0x09;static void pca9685MspInit(pca9685ConfigStruct *pca9685ConfigStructAddress);
static void pca9685Reset(pca9685ConfigStruct *pca9685ConfigStructAddress);void pca9685Init(pca9685ConfigStruct *pca9685ConfigStructAddress)
{
pca9685MspInit(pca9685ConfigStructAddress);
pca9685Reset(pca9685ConfigStructAddress);
}static void pca9685MspInit(pca9685ConfigStruct *pca9685ConfigStructAddress)
{
__HAL_RCC_I2C2_CLK_ENABLE();
pca9685ConfigStructAddress->i2cConfig.Instance = pca9685ConfigStructAddress->i2cHardwareAddress;
pca9685ConfigStructAddress->i2cConfig.Init.ClockSpeed = pca9685ConfigStructAddress->i2cSpeed;
pca9685ConfigStructAddress->i2cConfig.Init.DutyCycle = I2C_DUTYCYCLE_2;
pca9685ConfigStructAddress->i2cConfig.Init.OwnAddress1 = 0;
pca9685ConfigStructAddress->i2cConfig.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
pca9685ConfigStructAddress->i2cConfig.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
pca9685ConfigStructAddress->i2cConfig.Init.OwnAddress2 = 0;
pca9685ConfigStructAddress->i2cConfig.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
pca9685ConfigStructAddress->i2cConfig.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&pca9685ConfigStructAddress->i2cConfig) != HAL_OK)
Error_Handler();GPIO_InitTypeDef GPIO_InitStruct = {0};
switch ((uint32_t)pca9685ConfigStructAddress->i2cConfig.Instance){
case (uint32_t)I2C1:
break;case (uint32_t)I2C2:
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
break;default:
break;}
}static void pca9685Write(pca9685ConfigStruct *pca9685ConfigStructAddress, uint8_t address, uint8_t data)
{
//需要将地址手动左移一位
//发送从高位开始,开始信号后首字节为7bit addr + 1bit w/r w:0 r:1
HAL_I2C_Mem_Write(&pca9685ConfigStructAddress->i2cConfig, pca9685ConfigStructAddress->pca9685Address << 1, address, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}static uint8_t pca9685Read(pca9685ConfigStruct *pca9685ConfigStructAddress, uint8_t address)
{
uint8_t data;
//需要将地址手动左移一位
HAL_I2C_Mem_Read(&pca9685ConfigStructAddress->i2cConfig, pca9685ConfigStructAddress->pca9685Address << 1, address, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
//从机发数据ack是不应答的,只有接收才会应答
return data;
}static void pca9685Reset(pca9685ConfigStruct *pca9685ConfigStructAddress)
{
pca9685Write(pca9685ConfigStructAddress, pca9685Mode1RegisterAddress, 0x00); //清空
pca9685Write(pca9685ConfigStructAddress, pca9685Mode1RegisterAddress, 0xa1); //复位 + 基本配置
}void pca9685ConfigPwmFreq(pca9685ConfigStruct *pca9685ConfigStructAddress, float freq)
{
freq = 25000000 / 4096 / freq - 3; //-3为补偿uint8_t oldMode = pca9685Read(pca9685ConfigStructAddress, pca9685Mode1RegisterAddress);
pca9685Write(pca9685ConfigStructAddress, pca9685Mode1RegisterAddress, (oldMode & 0x7F) | 0x10); //清除bit7防止复位 + 进入睡眠
pca9685Write(pca9685ConfigStructAddress, pca9685PrescaleRegisterAddress, (uint8_t)freq); //修改频率
pca9685Write(pca9685ConfigStructAddress, pca9685Mode1RegisterAddress, oldMode & 0xef); //解除睡眠
}void pca9685ConfigPwmDutyCycle(pca9685ConfigStruct *pca9685ConfigStructAddress, uint8_t number, float dutyCycle)
{
uint16_t dutyCycleBackup = dutyCycle * 4096 + 0.5;
pca9685Write(pca9685ConfigStructAddress, pca9685UpLRegisterAddress + 4 * number, 0);
pca9685Write(pca9685ConfigStructAddress, pca9685UpMRegisterAddress + 4 * number, 0);
pca9685Write(pca9685ConfigStructAddress, pca9685DownLRegisterAddress + 4 * number, dutyCycleBackup);
pca9685Write(pca9685ConfigStructAddress, pca9685DownMRegisterAddress + 4 * number, dutyCycleBackup >> 8);
}
#include "main.h"
#include "stdbool.h"#include "pca9685.h"bool msFlag; //每过1毫秒就置truestatic void systeamInit();
static void timerServe();static void servo();void loop()
{
systeamInit();
HAL_Delay(1000);while (true){
timerServe();}
}static void timerServe()
{
if (!msFlag)
return;
msFlag = false;servo();
}static void servo()
{
static pca9685ConfigStruct pca9685Addr0x40 = {.i2cHardwareAddress = I2C2,.i2cSpeed = 100000,.pca9685Address = 0x40};static uint8_t switchStep;
static uint16_t timer1;
switch (switchStep){
case 0:
pca9685Init(&pca9685Addr0x40);
pca9685ConfigPwmFreq(&pca9685Addr0x40, 50);
switchStep++;
break;case 1:
pca9685ConfigPwmDutyCycle(&pca9685Addr0x40, 0, 0.025); //角度0
switchStep++;
break;case 2:
if (timer1++ >= 1000)
timer1 = 0, switchStep++;
break;case 3:
pca9685ConfigPwmDutyCycle(&pca9685Addr0x40, 0, 0.075); //角度90
switchStep++;
break;case 4:
if (timer1++ >= 1000)
timer1 = 0, switchStep++;
break;case 5:
pca9685ConfigPwmDutyCycle(&pca9685Addr0x40, 0, 0.125); //角度180
switchStep++;
break;case 6:
if (timer1++ >= 1000)
timer1 = 0, switchStep++;
break;default:
switchStep = 1;
break;}
}void SysTick_Handler()
{
HAL_IncTick();
msFlag = true;
}static void SystemClock_Config()
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
Error_Handler();RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
Error_Handler();
}static void MX_GPIO_Init()
{
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}static void systeamInit()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
}

pca9685 stm32 hal iic相关推荐

  1. STM32 HAL 硬件IIC+DMA+简单图形库控制OLED

    目录 前言 一.建立工程 二.编写和移植 前期准备 驱动部分修改 三.使用和验证 结论 (2022年1月22日重制)本文主要是移植带简单图形库的程序,如果只是实现DMA控制,建议看[0.96寸 OLE ...

  2. STM32 HAL I2C(IIC)通信的序列传输(restart condition)

    STM32 HAL I2C(IIC)通信的序列(Seq)传输函数(restart condition) neozng1@hnu.edu.cn 文章目录 STM32 HAL I2C(IIC)通信的序列( ...

  3. STM32 HAL库IIC驱动

    1. STM32上IIC的一些争议 关于STM32的IIC驱动,网上有很多争论,究竟是使用STM32自带的硬件IIC还是用IO口和软件模拟IIC呢?下面这个图形象展示了这些争论.总结一些:ST为了规避 ...

  4. stm32 hal库 AS5600磁编码器IIC通信读取角度

    stm32 hal库 AS5600磁编码器IIC通信读取角度 下载

  5. 关于stm32 hal 库 iic 一直是 busy 问题

    最近在用st hal iic 发现 MX_I2C1_Init(); 后 iic 就处于BUSY状态 代码跟踪后发现 具体到 HAL_I2C_MspInit 中 __HAL_RCC_I2C1_CLK_E ...

  6. 温湿度传感器驱动SHT85 单片机STM32 HAL库

    功能介绍:读取传感器SHT85数据,转换成温度.湿度 .饱和水蒸气含量. 注意事项: SDA脚设置为开漏输出,外部上拉电阻10k.或者设置成推挽,软件切换SDA输入输出. 调试时可适当加长延时时间. ...

  7. STM32 HAL库详解

    STM32 HAL库整体总结 STM32 之二 HAL库详解 及 手动移植 本篇博客是对以上参考资源的一个二次总结与整理. 1. HAL库文件结构 对于开发人员而言,首先要清楚 HAL 库的文件结构. ...

  8. STM32 HAL库 驱动 MT6701 磁编码器

    写在前面: MT6701 是 MagnTek 推出的新一代基于差分霍尔感应原理的磁性角度编码器芯片.值得一提的是 MT6701不仅提供 0~360° 的角度信号,而且还提供了一个"按压&qu ...

  9. STM32 HAL 驱动I2C总线0.91寸OLED模块(基于SSD1306显示驱动芯片)

    STM32 HAL 驱动I2C总线0.91寸OLED模块(基于SSD1306显示驱动芯片) 基于SSD1306驱动芯片的OLED模块有多种型号,有0.91英寸,0.96英寸等等.OLED采用单色显示方 ...

最新文章

  1. 【lidar】3D目标检测PointPillars:论文解读、代码解读、部署实现(2)
  2. 安卓真机测试安装时报错
  3. linux先运行后面指令,Linux基础命令(6)
  4. 零起步了解RK3288环境搭建以及版本编译
  5. 显示网格_快速制图软件 Edraw Max教程:Edraw Max怎么显示出网格线?
  6. JAVA梦幻之星攻略_梦幻之星2_《梦幻之星携带版2》图文详尽攻略 - 梦幻之星携带版2:无限...
  7. python使用matplotlib绘图sigmoid_使用matplotlib库绘制函数图
  8. 休眠事实:有利于双向集vs列表
  9. tablednd保存 php,JQuery-tableDnD 拖拽的基本使用介绍
  10. 日本惠普发表14.1型液晶内藏笔记本PC「dv4」系列2种模式
  11. Nginx源码分析 - Event事件篇 - Event模块的进程初始化(18)
  12. 网页设计制作CSS实现隔行换色两种方法
  13. java计算机毕业设计幼儿园管理系统源码+数据库+系统+lw文档+部署
  14. 简易旋转倒立摆及控制装置-电赛训练
  15. 英特尔驱动程序下载_如何修复英特尔计算机上的“此计算机未验证正在安装的驱动程序”...
  16. 动作捕捉用于索并联机构中的理论验证
  17. 截止失真放大电路_这些基本放大器的知识,你会了吗?
  18. poj 3067 Japan
  19. Mac平台直播推流搭建
  20. 公安部:“净网2018”侦破网络犯罪案件57519起

热门文章

  1. 取代C++?谷歌开源编程语言Carbon,网友评价太真实了
  2. C语言实现老鼠走迷宫(附源码)
  3. 回村创业养猪有什么需要注意的?
  4. Poco官方PPT_010-Types双语对照翻译
  5. z世代消费力白皮书_“Z世代”的世界 消费流里的商机
  6. vector 基本使用方法
  7. 2019江苏计算机一级考试题库和答案,2019年全国计算机等级考试一级考试试题库及答案.docx...
  8. 2021前端JavaScript面试题及答案
  9. 市场调查与分析概述2
  10. 为何 java 中 int 类型的取值范围是 [-2147483648, 2147483647]