STM32F407配置pca9685驱动


pca9685是16路12位PWM信号发生器,可用于控制舵机、led、电机等设备,i2c通信,节省主机资源。在淘宝上随处可见,Arduino用它非常方便,不过STM32要想使用它必须要写好驱动才行,本文简述如何配置其驱动以及一些需要注意的地方。

  • STM32F407配置pca9685驱动

    • pca9685简介
    • pca9685驱动
      • pcf8574.h:
      • pcf8574.c:
    • 应用与调试

pca9685简介

当然对于老手,看datasheet是最好的选择pca9685datasheet
对于我这种新手,自然是看高手的文章比较容易上手了~

我在网上看到的对pca9685总结的最好的一篇文章推荐给大家:生命不息折腾不止
博主写得非常详细,本文某些片段也是参考博主的这篇文章,在此致谢。

pca9685用的是IIC通信,如果有同学对IIC不熟悉,要先去了解一下~

pca9685驱动

网上有不少写pca9685的文章,写驱动的也有,不过我试过的大多有错误,我详细地进行了修改,并且调试成功,走了不少弯路。

pcf8574.h:

头文件的话主要就是寄存器地址和IIC通信的函数声明,比较简单。

内部地址(hex) 名称 功能
Harry Potter Gryffindor 90
Hermione Granger Gryffindor 100
Draco Malfoy Slytherin 90
00 MODE1 设置寄存器1
01 MODE2 设置寄存器2
02 SUBADR1 i2c-bus subaddress1
03 SUBADR2 i2c-bus subaddress2
04 SUBADR3 i2c-bus subaddress3
05 ALLCALLADR
06 LED0_ON_L
07 LED0_ON_H
08 LED0_OFF_L
09 LED0_OFF_H
0x06 + 4*X LEDX_ON_L
0x06 + 4*X + 1 LEDX_ON_H
0x06 + 4*X + 2 LEDX_OFF_L
0x06 + 4*X + 3 LEDX_OFF_H
… 上面共16路通道
FA ALL_LED_ON_L
FB ALL_LED_ON_H
FC ALL_LED_OFF_L
FD ALL_LED_OFF_H
FE PRE_SCALE 控制周期的寄存器
FF TestMode

照着上面的表格写头文件就好了 - -

#ifndef __PCF8574_H
#define __PCF8574_H
#include "sys.h"
#include "myiic.h"#define PCA9685_adrr 0x80
#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 0xFDvoid PCA9685_write(unsigned char reg,unsigned char data);
u8 PCA9685_read(unsigned char reg);
void setPWMFreq(u8 freq);
void setPWM(u8 num, u16 on, u16 off);
void down();
void up();#endif

pcf8574.c:

PCA9685的读写操作没什么好说的,直接调用原子哥写好的IIC相关函数即可:

void PCA9685_write(unsigned char reg,unsigned char data)
{IIC_Start();IIC_Send_Byte(PCA9685_adrr);IIC_Wait_Ack();IIC_Send_Byte(reg);IIC_Wait_Ack();IIC_Send_Byte(data);IIC_Wait_Ack();IIC_Stop();
}
u8 PCA9685_read(unsigned char reg)
{u8 res;IIC_Start();IIC_Send_Byte(PCA9685_adrr);IIC_Wait_Ack();IIC_Send_Byte(reg);IIC_Wait_Ack();    IIC_Start();                IIC_Send_Byte(PCA9685_adrr|0X01);IIC_Wait_Ack();res=IIC_Read_Byte(0);       IIC_Stop();             return res;
}

设置PWM波的频率,看下面这个公式即可:

其中osc_clock是时钟,根据上面的寄存器设置选择是内部25MHz时钟还是外部时钟。
update_rate是频率,比如周期是20ms,那么频率就是50。
注意:实际应用中发现有误差,需要加入校准,要把udpate_rate乘以0.915。
包括从网上下载的arduino驱动中也加入了此校准。
注意要使用浮点型变量作为中间量,否则会计算错误,另外不要忘记四舍五入。

void setPWMFreq(u8 freq)
{u8 prescale,oldmode,newmode;double prescaleval;prescaleval = 25000000.0/(4096*freq*0.915);prescale = (u8)floor(prescaleval+0.5)-1;oldmode = PCA9685_read(PCA9685_MODE1);newmode = (oldmode&0x7F) | 0x10; // sleepPCA9685_write(PCA9685_MODE1, newmode); // go to sleepPCA9685_write(PCA9685_PRESCALE, prescale); // set the prescalerPCA9685_write(PCA9685_MODE1, oldmode);delay_ms(5);PCA9685_write(PCA9685_MODE1, oldmode | 0xa1);
}

setPWM函数,向相应的寄存器(LED0_ON_L、LED0_ON_H、LED0_OFF_L、LED0_OFF_H)写值即可。
其中num为舵机PWM输出引脚0~15,on是PWM上升计数值0~4096,off是PWM下降计数值0~4096。

他的PWM发生原理是这样的:

一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,off/4096的值就是PWM的占空比。

void setPWM(u8 num, u16 on, u16 off)
{PCA9685_write(LED0_ON_L+4*num,on);PCA9685_write(LED0_ON_H+4*num,on>>8);PCA9685_write(LED0_OFF_L+4*num,off);PCA9685_write(LED0_OFF_H+4*num,off>>8);
}

为了方便使用,我写了一个输入角度输出相应PWM值(off值)的函数。
这个要针对舵机进行修改,我用的是乐幻索尔的LDX218双轴舵机:

周期20ms,所以在设置频率的时候要设为50;占空比0.5ms~2.5ms分别对应0°~180°,且成线性关系,所以计算公式为:

PWM=4096×0.5+(2.5−0.5)×angle/18020 P W M = 4096 × 0.5 + ( 2.5 − 0.5 ) × a n g l e / 180 20

PWM=4096\times\frac{0.5+(2.5-0.5)\times angle/180}{20}

u16 calculate_PWM(u8 angle){return (int)(204.8*(0.5+angle*1.0/90));
}

然后就是一些动作组了,这个就随便写一个8个舵机全部置零位和全部置90°:
注意IIC通信间隔的问题,每调用一次setPWM()函数就要延迟1ms,否则会出现莫名其妙的BUG,这个很重要~

void down(){u16 pwm = calculate_PWM(0);setPWM(0x0,0,pwm);delay_ms(1);setPWM(0x1,0,pwm);delay_ms(1);setPWM(0x2,0,pwm);delay_ms(1);setPWM(0x3,0,pwm);delay_ms(1);setPWM(0x4,0,pwm);delay_ms(1);setPWM(0x5,0,pwm);delay_ms(1);setPWM(0x6,0,pwm);delay_ms(1);setPWM(0x7,0,pwm);
}void up(){u16 pwm = calculate_PWM(90);setPWM(0x0,0,pwm);delay_ms(1);setPWM(0x1,0,pwm);delay_ms(1);setPWM(0x2,0,pwm);delay_ms(1);setPWM(0x3,0,pwm);delay_ms(1);setPWM(0x4,0,pwm);delay_ms(1);setPWM(0x5,0,pwm);delay_ms(1);setPWM(0x6,0,pwm);delay_ms(1);setPWM(0x7,0,pwm);
}

应用与调试

我是想做一个用蓝牙控制一个四足机器人的,机器人有8个舵机,完整的工程代码已经跑通,感兴趣的可以下载看看:
蓝牙控制8个舵机(STM32F407+pca9685+HC06)

STM32F407配置pca9685驱动相关推荐

  1. STM32F407配置PLLI2SCLK实现特定50MHz时钟驱动83848

    STM32F407配置PLLI2SCLK实现特定50MHz时钟驱动83848 MCO2时钟输出时钟树介绍 PLLI2S配置函数 MCO2输出设置 在使用83848以太网芯片时需要输出一路50MHz的时 ...

  2. 配置windows驱动开发环境

    配置windows驱动开发环境                    撰写:jiftle 时间:2011-09-09 14:30                     windows驱动开发需要wd ...

  3. linux wlan进程名称,linux无线网络配置无线网卡驱动安装与wlan802.11配置

    Linux无线网络配置--无线网卡驱动安装与WLAN 802.11 配置 Linux无线网络配置--无线网卡驱动安装与WLAN 802.11配置2008-05-10 18:27 20739人阅读 评论 ...

  4. Windows10 配置 Nvidia 驱动与 Cuda 环境搭建

    title: Windows10 配置 Nvidia 驱动与 Cuda 环境搭建 mathjax: false date: 2021-04-17 12:50:27 tags: [Environment ...

  5. 1:STM32CubeMX配置STM32F103C8T6驱动-下载软件配置RCC,CAN1,USART1

    1:下载软件 点击 这里立即下载,共454M. 2:通过STM32CubeMX配置USART1,CAN1 1:创建工程 创建文件夹存放工程 添加工程名称及路径: 为每个驱动单独创建.c和.h文件. 2 ...

  6. jboss eap mysql_JBOSS EAP 6 系列三 Oracle、Mysql数据源的配置(驱动)—认识模块的使用...

    本文介绍JBOSS EAP 6.2中Oracle数据源的配置方式.结合之前JBOSS EAP 6.2新功能,本文初识JBOSS模块申明式容器这一特性. 模块申明式容器:JBOSS EAP不再有lib的 ...

  7. 新电脑配置显卡驱动及CUDA、CUDNN环境

    新电脑配置显卡驱动及CUDA.CUDNN环境 下载显卡驱动及相应版本CUDA及CUDNN 1.查看硬件配置:右键此电脑点击管理 →点击设备管理器→点击显示适配器→查看独立显卡 2.网页搜索英伟达驱动下 ...

  8. Arduino与Proteus仿真实例-PCA9685驱动伺服电机仿真

    PCA9685驱动伺服电机仿真 1.伺服电机介绍 伺服电机是一种旋转执行器或线性执行器,可以精确控制角度或线性位置.速度和加速度. 它由一个合适的电机组成,该电机耦合到一个用于位置反馈的传感器. 它还 ...

  9. WEMOS D1 R1/R2 [ESP8266] + PCA9685 驱动舵机

    WEMOS D1 R1/R2 [ESP8266] + PCA9685 驱动舵机 PCA9685 16-Channel 12-BIT PWM Driver,某些淘宝卖家只是标注了16路舵机驱动模块. P ...

最新文章

  1. 我们是如何解决复杂系统扩展性问题的
  2. R语言ggplot2时间序列可视化并在特定日期处添加竖线实战
  3. go语言panic机制的原理
  4. python tushare获取股票数据并可视化_荐Python获取股票数据及其可视化--基于tushare库...
  5. 工作203:实现预览效果
  6. vm8中装了redhat9 在安装vmwaretools的时候老是出现gcc位置错误
  7. 1.13 编程基础之综合应用 05 素数回文数的个数 python
  8. 组合数学 —— 康托展开
  9. Good Bye 2021: 2022 is NEAR A-Integer Diversity(水题)
  10. linux gd结构体,U-Boot中gd的定义和使用
  11. PyTorch学习—21.GPU的使用
  12. Redis 不安全临时文件漏洞
  13. 史上最详细的Maven安装教程以及Maven和eclipse集成
  14. matlab meshlab,MeshLab(网格模型处理软件)下载-MeshLab官方版下载[电脑版]-PC下载网
  15. GB2312/GBK编码规则及单片机汉显字库算法
  16. 无线网的dhcp服务器是什么意思,DHCP是什么意思
  17. 漫画:骚操作系列(必须掌握的疯子找座问题)
  18. Day13-寻觅踪迹
  19. 帝国CMS 批量修改信息标题方法
  20. 电脑使用图片转换器打开heic图片方法

热门文章

  1. CSS的世界(十四)
  2. redis分布式锁的原子保证
  3. python文本匹配_python 匹配@
  4. nodejs aes 加解密
  5. Linux shell实现阶乘
  6. samba -smb开启v2协议
  7. Java的应用领域有哪些
  8. Object转byte[];byte[]转Object
  9. 网络分析仪 smith圆图调试
  10. uni-app项目(首页)