stm32 pca9685 舵机使用

2019-07-14 19:53发布

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);
}
/*********************************************************************************************************
** º¯ÊýÃû³Æ: SM_Write
** ¹¦ÄÜÃèÊö: SMBus ¶à×Ö½Úдº¯Êý,´ÓÏò¸ø¶¨´æ´¢Æ÷µØÖ·¿ªÊ¼Ð´¶à¸ö×Ö½Ú
** Êä¡¡  Èë: ´ýд´æ´¢Æ÷ÆðʼµØÖ·£¨1×Ö½Ú£©addr
**                         ´ýдÊý¾Ý I2C_Buf
**                         ´ýдÊý¾Ý¸öÊý count
** Êä¡¡         ³ö: ÎÞ
********************************************************************************************************/
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
        }
}
/*********************************************************************************************************
** º¯ÊýÃû³Æ: SM_Read
** ¹¦ÄÜÃèÊö: SMBus ×Ö½Ú¶Áº¯Êý,´Ó¸ø¶¨´æ´¢Æ÷µØÖ·¶ÁÒ»¸ö×Ö½Ú
** Êä¡¡  Èë: ´ý¶Á´æ´¢Æ÷µØÖ·£¨1×Ö½Ú£©addr
**                         ´ý¶ÁEEPROMоƬµÄÆ÷¼þµØÖ· 0xA0
** Êä¡¡         ³ö: Êý¾Ý
********************************************************************************************************/
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
0条回答

一周热门 更多>