PCA9685与 NXP1768单片机iic通信,扩展PWM端口。已调试成功。
一直在用NXP的单片机做各种开发, 最近遇到了这么个问题,就是单片机的PWM端口不够用,公司硬件工程师推荐使用NXP的PCA9685芯片扩展,PCA9685 是一款 I2C 总线接口的 16 位 LED 控制器。一个芯片可以扩展出16路PWM,我们用了两个,成功扩展出32路PWM端口,再也不用使用GPIO去模拟了。由于硬件设计板子,投版,制版流程太慢,所以我在淘宝上买了个PCA9685的开发板,很便宜,十几块钱。
切入正题,怎么使用PCA9685扩展PWM端口呢?此芯片是通过IIC与其他MCU通信的,程序参考了http://bbs.elecfans.com/forum.php?mod=viewthread&tid=1104135&extra=page=1&orderby=dateline有关51单片机驱动程序修改的有兴趣可以看看,下面是修改后的程序。
接线方法:VCC -3.3V 给芯片供电,GND-接地 SCL-接单片机SCL(时钟)
//PCA9685 扩展芯片相关
#define PCA9685_I2C_ID 1
#define PCA9685_adrr 0x80// 1+A5+A4+A3+A2+A1+A0+w/r 最后一位0代表写地址,1代表读地址
//片选地址,将焊接点置1可改变地址,
// 需要注意的是芯片的IIC地址在不做任何焊接的情况下是0X80,有些淘宝卖家认为是0X40。
#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
/*****************************************************************************
** Function name: PCA9685_write
** Descriptions: 向PCA9685写地址或者数据
** parameters: id:i2c number
** address: Chip or register address
data:Data to be written
** Returned value: none
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
void PCA9685_write(KC_UINT8 id, KC_UINT8 address,KC_UINT8 data)
{
i2c_start(id);
i2c_write_byte(id,PCA9685_adrr); //PCA9685的片选地址
i2c_write_byte(id,address); //写地址控制字节
i2c_write_byte(id,data); //写数据
i2c_stop(id);
}
/*****************************************************************************
** Function name: PCA9685_read
** Descriptions: Read data from the address value in PCA9685
** parameters: id:i2c number
** address: Chip or register address
** Returned value: The data that was read
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
KC_UINT8 PCA9685_read(KC_UINT8 id, KC_UINT8 address)
{
KC_UINT8 data;
i2c_start(id);
i2c_write_byte(id,PCA9685_adrr); //PCA9685的片选地址
i2c_write_byte(id,address);
i2c_start(id);
i2c_write_byte(id,PCA9685_adrr|0x01); //地址的第八位控制数据流方向,就是写或读
data=i2c_read_byte(id);
i2c_stop(id);
return data;
}
/*****************************************************************************
** Function name: PCA9685_reset
** Descriptions: PCA9685_reset
** parameters: none
** Returned value: none
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
void PCA9685_reset(void)
{
SCL_OUT(PCA9685_I2C_ID);
SCLL(PCA9685_I2C_ID);
i2c_delay(I2C_DELAY_TIME);
i2c_stop(PCA9685_I2C_ID);
i2c_delay(I2C_DELAY_TIME);
PCA9685_write(PCA9685_I2C_ID,PCA9685_MODE1,0x0);
}
/*****************************************************************************
** Function name: PCA9685_begin
** Descriptions: PCA9685_begin
** parameters: none
** Returned value: none
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
void PCA9685_begin(void)
{
PCA9685_reset();
}
/*****************************************************************************
** Function name: setPWMFreq
** Descriptions: Set PWM frequency
** parameters: freq:PWM frequency
** Returned value: none
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
void setPWMFreq(float freq)
{
KC_UINT8 prescale,oldmode,newmode;
float prescaleval;
freq *= 0.92; // Correct for overshoot in the frequency setting
prescaleval = 25000000;
prescaleval /= 4096;
prescaleval /= freq;
prescaleval -= 1;
prescale = floor(prescaleval + 0.5);
oldmode = PCA9685_read(PCA9685_I2C_ID,PCA9685_MODE1);
newmode = (oldmode&0x7F) | 0x10; // sleep
PCA9685_write(PCA9685_I2C_ID,PCA9685_MODE1, newmode); // go to sleep
PCA9685_write(PCA9685_I2C_ID,PCA9685_PRESCALE, prescale); // set the prescaler
PCA9685_write(PCA9685_I2C_ID,PCA9685_MODE1, oldmode);
i2c_delay(I2C_DELAY_TIME);
PCA9685_write(PCA9685_I2C_ID,PCA9685_MODE1, oldmode | 0xa1);
}
/*****************************************************************************
** Function name: setPWM
** Descriptions: Set PWM frequency
** parameters: 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的占空比。
** Returned value: none
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
void setPWM(KC_UINT8 num, KC_UINT16 on, KC_UINT16 off)
{
PCA9685_write(PCA9685_I2C_ID,LED0_ON_L+4*num,on);
PCA9685_write(PCA9685_I2C_ID,LED0_ON_H+4*num,on>>8);
PCA9685_write(PCA9685_I2C_ID,LED0_OFF_L+4*num,off);
PCA9685_write(PCA9685_I2C_ID,LED0_OFF_H+4*num,off>>8);
}
/*****************************************************************************
** Function name: PCA9685_init
** Descriptions: PCA9685 chip init
** parameters: freq:PWM frequency
** Returned value: none
** Author: joelv
** Date: 06/20/2020
*****************************************************************************/
void PCA9685_init(KC_UINT8 freq)
{
PCA9685_begin();
setPWMFreq(freq);
}
PCA9685_write();PCA9685_read();i2c_start();i2c_stop();i2c_wait_ack();等函数都是使用公司内部iic驱动程序,不便公布,请读者谅解。但这些都是基础的iic驱动程序,读者只需要根据IIC时序图自己编写或者查找其他单片机的IIC驱动(51,STM32等等的很普遍),另一方面,我所使用的单片机也不常见,一般人也用不到。有兴趣的开发者可使用适用的单片机驱动替换即可使用。
在使用时,仅需要调用初始化函数,PWM频率我当时设置为140HZ,然后调用SetPWM()函数即可控制各个PWM管脚。
PCA9685与 NXP1768单片机iic通信,扩展PWM端口。已调试成功。相关推荐
- 16F877A和24C02通信汇编语言,pic单片机IIC通信读24C02程序例 16F877A 主频4M
#define _iic_h_//pic单片机IIC通信初始化函数声明 void iiccsh(void); //pic单片机IIC通信读外围设备函数声明 //功能:传送一个8位地址,返回一个8位数据 ...
- PIC单片机 IIC通信及实现
IIC通信 IIC是一种只需要2根数据线就可以实现数据通信的总线式结构.IIC采用主从式通信方式,通信过程完全由主设备决定.完整的通信流程是主设备发送起始信号给从设备,再发送地址来选中从设备,然后 ...
- 微信小程序控制STC12单片机蓝牙通信与PWM控制舵机
此项目主要用蓝牙小程序,蓝牙通信控制舵机开关灯的作用. 下面我们先看实物.机械结构是一个机械朋友(LT)设计的,十分感谢他. 1.1小程序 WXML的程序: <button bindtap=&q ...
- 单片机中存储器扩展位地址线怎么算_51单片机CPU结构各部件的原理详细分析
一. 51单片机串行口工作原理 MCS-51系列单片机片内有一个串行I/O端口,通过引脚RXD(P3.0)和TXD(P3.1)可与外设电路进行全双工的串行异步通信. 1.串行端口的基本特点 8031单 ...
- 华大单片机HC32L130/HC32L136从机IIC通信
从机IIC理论知识 主机IIC的做法比较多,从机IIC的就相对比较难一点. 先补充一下从机IIC的思路: 先看IIC时序图,然后根据时序图理清IIC从机需要做哪些判断: 从机发送: ·判断IIC ST ...
- 扫盲教程:单片机IIC基础通信
单片机IIC基础通信 1 接口定义 2 程序实例 阅读提示:本章主要讲解过去电路使用较多的24C02- 24C512存储器,对于现在 主流的STC15W系列单片机,通常都具有内部比较器与DataFla ...
- 51单片机开发板模拟实现IIC通信
51单片机模拟实现IIC通信 IIC.h IIC.c main.c 总结 IIC.h #ifndef _iic_h_ #define _iic_h_ #include <reg52.h> ...
- 51单片机(IO模拟IIC通信)
单片机作为主机 sbit SDA = P1^0; sbit SCL = P1^1; IIC数据操作:在iic总线上,数据伴随时钟脉冲,一位一位的传送的,数据位由高到低传送,每位数据占一个时钟脉冲.在时 ...
- PCF8591 ---AD\DA转换器的使用(IIC通信的软件模拟与应用) (by 51单片机)
依旧是借着蓝桥杯的机会,来学习一些模块,和软件模拟一些通信方式. 今天学习的模块是PCF8591,一款AD\DA转换器,使用IIC通信方式. 芯片的内部框图如下所示: 各引脚作用如下表所示: 仍旧和之 ...
- 51单片机常用通信方式之IIC通信(二)
IIC通信是一种同步通信方式,同步通信是采用一个同步时钟线,连到收发双方,使收发双方达到完全同步.则IIC通信硬件连接就有四根线VCC.GND.SDA.SCL,SDA是传送数据的,SCL是控制时序的, ...
最新文章
- 如果你是C开发人员请看这三个显式编程技巧
- java web开发中Filter使用Annotation配置 (转载)
- 4、CSS 外边距margin
- 【Nutch2.2.1基础教程之1】nutch相关异常
- 系统学习redis之二——redis集群搭建
- LeetCode 1267. 统计参与通信的服务器(计数)
- 通过一个用户管理实例学习路由react-router-dom知识
- python相册特效模块_PIL包中Image模块的convert()函数的具体使用
- C语言程序设计知识必备pdf,C语言程序设计基础知识要点.pdf
- ntko 发生错误:保存html到临时文件目录发生错误,【ntko文件存取错误】_如何处理OA系统在线阅读或编辑文档时提示“文件存取错误”的问题...
- 智能算法之免疫算法求解TSP问题
- C语言--三次方程数值求解
- 加拿大 计算机学校排名2015,2015年加拿大大学综合排名
- 交流电路计算方法:复阻抗和相量法
- 使用Unity制作一个RPG游戏(1)
- sql数据库习题总集
- Android 实现分割线的几种方式
- 使用Vue3实现360度全景效果
- [禅悟人生]真知从实践中来
- mysql练习题及答案_mysql练习题及答案.doc