stm32 pca9685 舵机使用
时间:10-02
整理:3721RD
点击:
void SM_Write(u8 addr,u8 dat)
{
// u8 err = 0;
I2C_Start();
I2C_write_data(PCA9685_ad); // ???? + WRITEI2C_write_data(0xA0 | WRITE);
I2C_Ack();
I2C_write_data(addr); // μ??·
I2C_Ack();
I2C_write_data(dat);
I2C_Ack();
I2C_Stop();
Delay_us(100);
}
/*********************************************************************************************************
** oˉêy??3?: SM_Write
** 1|?ü?èê?: SMBus ?à×??úD′oˉêy,′ó?ò???¨′?′¢?÷μ??·?aê?D′?à??×??ú
** ê??? è?: ′yD′′?′¢?÷?eê?μ??·£¨1×??ú£?addr
** ′yD′êy?Y I2C_Buf
** ′yD′êy?Y??êy count
** ê??? 3?: ?T
********************************************************************************************************/
void SM_WriteN(u8 addr,u8 count)
{
u8 i;
for(i=0;i<count;i++)
{
SM_Write(addr+i,I2C_Buf);
Delay_us(50); // waiting for write cycle to be completed
}
}
/*********************************************************************************************************
** oˉêy??3?: SM_Read
** 1|?ü?èê?: SMBus ×??ú?áoˉêy,′ó???¨′?′¢?÷μ??·?áò???×??ú
** ê??? è?: ′y?á′?′¢?÷μ??·£¨1×??ú£?addr
** ′y?áEEPROMD???μ??÷?tμ??· 0xA0
** ê??? 3?: êy?Y
********************************************************************************************************/
u8 SM_Read(u8 addr)
{
u8 dat;
// u8 err = 0;
I2C_Start();
I2C_write_data(PCA9685_ad); // ???? + WRITEI2C_write_data(0xA0 | WRITE);
I2C_Ack();
I2C_write_data(addr); // μ??·
I2C_Ack();
I2C_Start();
I2C_write_data(PCA9685_ad|0x01); // ???? + READI2C_write_data(0xA0 | READ);
I2C_Ack();
dat = I2C_read_data();
I2C_Stop();
delay_ms(10);
return dat;
}
void setPWMFreq(u8 freq)
{
u8 prescale;
u8 oldmode;
u8 newmode;
float prescaleval;
freq *= 0.9; // 0.92 Correct for overshoot in the frequency setting (see issue #11).
prescaleval = 25000000;
prescaleval /= 4096;
prescaleval /= freq;
prescaleval -= 1;
prescale = floor(prescaleval + 0.5);
oldmode = SM_Read(PCA9685_MODE1);
newmode = ((oldmode&0x7F) | 0x10); // sleep
SM_Write(PCA9685_MODE1, newmode); // go to sleep
SM_Write(PCA9685_PRESCALE, prescale); // set the prescaler
SM_Write(PCA9685_MODE1, oldmode);
delay_ms(5);
SM_Write(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment.
// This is why the beginTransmission below was not working.
// Serial.print("Mode now 0x"); Serial.println(PCA9685_read(PCA9685_MODE1), HEX);
}
/*---------------------------------------------------------------
----------------------------------------------------------------*/
void setPWM(u8 num, u16 on, u16 off)
{
//Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off);
// I2C_GenerateSTART(I2C1,ENABLE);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
// I2C_Send7bitAddress(I2C1,PCA9685_adrr,I2C_Direction_Transmitter);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// I2C_SendData(I2C1,LED0_ON_L+4*num);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// I2C_SendData(I2C1,on);
// I2C_SendData(I2C1,on>>8);
// I2C_SendData(I2C1,off);
// I2C_SendData(I2C1,off>>8);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// I2C_GenerateSTOP(I2C1,ENABLE);
SM_Write(LED0_ON_L+4*num,on);
SM_Write(LED0_ON_H+4*num,on>>8);
SM_Write(LED0_OFF_L+4*num,off);
SM_Write(LED0_OFF_H+4*num,off>>8);
}
// Sets pin without having to deal with on/off tick placement and properly handles
// a zero value as completely off. Optional invert parameter supports inverting
// the pulse for sinking to ground. Val should be a value from 0 to 4095 inclusive.
void setPin(u8 num, u16 val, u8 invert)
{
if(val>4095)val=4095;
if (invert) {
if (val == 0) {
// Special value for signal fully on.
setPWM(num, 4096, 0);
}
else if (val == 4095) {
// Special value for signal fully off.
setPWM(num, 0, 4096);
}
else {
setPWM(num, 0, 4095-val);
}
}
else {
if (val == 4095) {
// Special value for signal fully on.
setPWM(num, 4096, 0);
}
else if (val == 0) {
// Special value for signal fully off.
setPWM(num, 0, 4096);
}
else {
setPWM(num, 0, val);
}
}
}
模拟/硬件IIC都试了,PC A9685没反应
参考网址:http://www.geek-workshop.com/thread-25046-1-2.html
{
// u8 err = 0;
I2C_Start();
I2C_write_data(PCA9685_ad); // ???? + WRITEI2C_write_data(0xA0 | WRITE);
I2C_Ack();
I2C_write_data(addr); // μ??·
I2C_Ack();
I2C_write_data(dat);
I2C_Ack();
I2C_Stop();
Delay_us(100);
}
/*********************************************************************************************************
** oˉêy??3?: SM_Write
** 1|?ü?èê?: SMBus ?à×??úD′oˉêy,′ó?ò???¨′?′¢?÷μ??·?aê?D′?à??×??ú
** ê??? è?: ′yD′′?′¢?÷?eê?μ??·£¨1×??ú£?addr
** ′yD′êy?Y I2C_Buf
** ′yD′êy?Y??êy count
** ê??? 3?: ?T
********************************************************************************************************/
void SM_WriteN(u8 addr,u8 count)
{
u8 i;
for(i=0;i<count;i++)
{
SM_Write(addr+i,I2C_Buf);
Delay_us(50); // waiting for write cycle to be completed
}
}
/*********************************************************************************************************
** oˉêy??3?: SM_Read
** 1|?ü?èê?: SMBus ×??ú?áoˉêy,′ó???¨′?′¢?÷μ??·?áò???×??ú
** ê??? è?: ′y?á′?′¢?÷μ??·£¨1×??ú£?addr
** ′y?áEEPROMD???μ??÷?tμ??· 0xA0
** ê??? 3?: êy?Y
********************************************************************************************************/
u8 SM_Read(u8 addr)
{
u8 dat;
// u8 err = 0;
I2C_Start();
I2C_write_data(PCA9685_ad); // ???? + WRITEI2C_write_data(0xA0 | WRITE);
I2C_Ack();
I2C_write_data(addr); // μ??·
I2C_Ack();
I2C_Start();
I2C_write_data(PCA9685_ad|0x01); // ???? + READI2C_write_data(0xA0 | READ);
I2C_Ack();
dat = I2C_read_data();
I2C_Stop();
delay_ms(10);
return dat;
}
void setPWMFreq(u8 freq)
{
u8 prescale;
u8 oldmode;
u8 newmode;
float prescaleval;
freq *= 0.9; // 0.92 Correct for overshoot in the frequency setting (see issue #11).
prescaleval = 25000000;
prescaleval /= 4096;
prescaleval /= freq;
prescaleval -= 1;
prescale = floor(prescaleval + 0.5);
oldmode = SM_Read(PCA9685_MODE1);
newmode = ((oldmode&0x7F) | 0x10); // sleep
SM_Write(PCA9685_MODE1, newmode); // go to sleep
SM_Write(PCA9685_PRESCALE, prescale); // set the prescaler
SM_Write(PCA9685_MODE1, oldmode);
delay_ms(5);
SM_Write(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment.
// This is why the beginTransmission below was not working.
// Serial.print("Mode now 0x"); Serial.println(PCA9685_read(PCA9685_MODE1), HEX);
}
/*---------------------------------------------------------------
----------------------------------------------------------------*/
void setPWM(u8 num, u16 on, u16 off)
{
//Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off);
// I2C_GenerateSTART(I2C1,ENABLE);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
// I2C_Send7bitAddress(I2C1,PCA9685_adrr,I2C_Direction_Transmitter);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// I2C_SendData(I2C1,LED0_ON_L+4*num);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// I2C_SendData(I2C1,on);
// I2C_SendData(I2C1,on>>8);
// I2C_SendData(I2C1,off);
// I2C_SendData(I2C1,off>>8);
// while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// I2C_GenerateSTOP(I2C1,ENABLE);
SM_Write(LED0_ON_L+4*num,on);
SM_Write(LED0_ON_H+4*num,on>>8);
SM_Write(LED0_OFF_L+4*num,off);
SM_Write(LED0_OFF_H+4*num,off>>8);
}
// Sets pin without having to deal with on/off tick placement and properly handles
// a zero value as completely off. Optional invert parameter supports inverting
// the pulse for sinking to ground. Val should be a value from 0 to 4095 inclusive.
void setPin(u8 num, u16 val, u8 invert)
{
if(val>4095)val=4095;
if (invert) {
if (val == 0) {
// Special value for signal fully on.
setPWM(num, 4096, 0);
}
else if (val == 4095) {
// Special value for signal fully off.
setPWM(num, 0, 4096);
}
else {
setPWM(num, 0, 4095-val);
}
}
else {
if (val == 4095) {
// Special value for signal fully on.
setPWM(num, 4096, 0);
}
else if (val == 0) {
// Special value for signal fully off.
setPWM(num, 0, 4096);
}
else {
setPWM(num, 0, val);
}
}
}
模拟/硬件IIC都试了,PC A9685没反应
参考网址:http://www.geek-workshop.com/thread-25046-1-2.html
搞了好几天了