PCA9685 is a chip with 12-bit precision and 16-channel PWM wave output based on IIC bus communication. When the chip was first launched by NXP, it was mainly used for LED switch dimming.
16-channel 12-bit PWM signal generator can be used to control servos, LEDs, motors and other devices, i2c communication, saving host resources.
Supplies1. Voltage
The voltage range of the digital circuit can accept 3.3 and 5V levels. In addition, there is a v+ pin, which is used to power the servo and can be connected to a slightly higher voltage.
2. I2C address
There are 6 address control pins, through which the I2C address of the device can be controlled.
The 7-bit I2C address is: 0x40 + A5:A0. If A5 to A0 are not processed, they are 0. If you want to set a position to 1, solder the pins together.
In addition, i2cdetect detects that there is still an address of 0x70, which is a universal address that can issue instructions to all slaves.
3. Enable pin
The module has an OE reverse enable pin, which is enabled at a low level. If it is not connected, the module is grounded by default, so it can be left unconnected for normal use.
Step 1: ON and OFF Registers for Each ChannelThere are 16 channels in total, and each channel has four registers: LEDX_ON_L, LEDX_ON_H, LEDX_OFF_L, and LEDX_OFF_H.
There is a 12-bit counter ACK in the system. ACK increases according to the cycle set by the PRE_SCALE register. It is compared with the above four registers every time it increases:
When ACK == LEDX_ON_H[3:0]:LEDX_ON_L is found, the X channel outputs a high level;
When ACK == LEDX_OFF_H[3:0]:LEDX_OFF_L is found, the X channel outputs a low level.
Step 2: PRE_SCALE RegisterThis register is used to set the cycle. You don't need to worry about the specific principle, just remember:
freq: the cycle to be set
prescaleval: the parameter to be written
Step 3: External Call InterfaceUse initialization and set directly.
If there is no output after setting, it may be that i2c writing failed. I encountered this situation at the beginning, and then I changed the i2c library and it worked. It is still mainly to use i2c correctly.
/*freq: the period to be set*/
void setPWMFreq(float freq);
/*
num: set the output change of the numth output port
on and off: cooperate to generate duty cycle 0~on is low level, to on is high level, to off is low level
*/
void setPWM(u8 num, u16 on, u16 off);
The above is not convenient to use, so it is encapsulated as a simple one. Directly input the duty cycle to be set. The period is 50, off: 15 means 1.5ms, which is convenient for controlling the servo
void set_pwm(u8 num, u8 off);
Step 4: Codingvoid setPWMFreq(float freq) { freq *= 0.9; float prescaleval = 25000000; prescaleval /= 4096; prescaleval /= freq; prescaleval -= 1; uint8_t oldmode = read8(PCA9685_MODE1); uint8_t newmode = (oldmode&0x7F) | 0x10; //准备进入sleep,设置时钟前必须先进入sleep模式Delay_ms(5);write8(PCA9685_MODE1, newmode);Delay_ms(5);write8(PCA9685_PRESCALE, prescaleval); p Delay_ms(5); oldmode &= 0xef; //清除sleep位write8(PCA9685_MODE1, oldmode);Delay_ms(5);write8(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment.}
void setPWM(uint8_t num, uint16_t on, uint16_t off) { write8(LED0_ON_L+4*num, on); write8(LED0_ON_H+4*num, on>>8); write8(LED0_OFF_L+4*num, off); write8(LED0_OFF_H+4*num, off>>8); }
void set_pwm(u8 num, u8 off) { setPWM(num, 0, (int)(off*20.48)); }
uint8_t read8(uint8_t reg_addr) { u8 data=0; I2C_BufferRead(PCA9685_SLAVE_ADDRESS, &data, reg_addr, 1); return data; } void write8(uint8_t reg_addr, uint8_t reg_dat) { I2C_ByteWrite(PCA9685_SLAVE_ADDRESS, reg_dat, reg_addr); }
Step 5: NoteSince I2C interface is often used, a library is written to facilitate porting. In the future, I only need to modify the package slightly each time I2C is used. The two interfaces are mainly used: I2C_BufferRead(PCA9685_SLAVE_ADDRESS, &data, reg_addr, 1); and I2C_ByteWrite(PCA9685_SLAVE_ADDRESS, reg_dat, reg_addr);
Comments
Please log in or sign up to comment.