MSP430系列单片机:PCA9685驱动多足机器人

多足机器人,是我大二暑假和大三开始玩的东西,刚好大四暑假留校又接触了MSP430,就想着把原来写的的代码也放到这里

控制多组舵机驱动机器人动作,用MSP430F5438A当主控器,PCA9685当驱动输出PWM方波的发生器,那下子驱动方式弄的我脑壳疼的哟,想想也是好笑。、

emmmm….PCA9685的手册好像没有中文,那下子也是看的脑袋大,好像这里有以前写的驱动原理,写完的就忘更新了….暑假就拿来看怎么驱动了。只记得个大概,IIC通讯协议方式通讯,先发送驱动器的物理地址确认是这个驱动器,得到应答后再开始发送数据,数据用数值形式发送到每个PWM方波输出口,一共可发送16路PWM方波。附上驱动代码。

IIC协议头文件

#ifndef _IIC_H_
#define _IIC_H_

#include "msp430.h"

typedef unsigned int uint;
typedef unsigned char uchar;

//引脚
#define IIC_SDA_PIN   (BIT0)
#define IIC_SCL_PIN   (BIT1)

//位宏
#define READ_SDA()      P2IN&BIT0

#define IIC_SDA_LO         P2OUT&=~BIT1
#define IIC_SDA_HI         P2OUT|=BIT1

#define IIC_SCL_LO         P2OUT&=~BIT3
#define IIC_SCL_HI         P2OUT|=BIT3

//SDA设置为输出输入
#define SDA_OUT()  P2DIR|=BIT1  
#define SDA_IN()   P2DIR&=~BIT1

//SCL设置为输出输入
#define SCL_OUT()  P2DIR|=BIT3
#define SCL_IN()   P2DIR&=~BIT3

//本构件所实现的函数列表
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_NAck(void);
void IIC_Ack(void);
void IIC_SendByte(uint dat);
uchar IIC_ReadByte(uchar ack);
uchar I2C_ReadByte(uchar DiviceID ,uchar address);
void I2C_WriteByte(uchar  ,uchar address,uchar );
void I2C_ReadNByte(uchar  ,uchar address,uchar ,uchar* );
#endif

IIC协议函数

#include "iic.h"

void IIC_delay_us(uchar x)//延时
{
  if(x==0)
    x=2;
  while(x--);
}


void IIC_Init(void)
{
   SDA_OUT();
   IIC_delay_us(2);
   SCL_OUT();
   IIC_delay_us(2);
}


void IIC_Start(void)//初始化IIC接口
{
  SDA_OUT();  
  IIC_SDA_HI;
  IIC_delay_us(2);
  IIC_SCL_HI;
  IIC_delay_us(2);
  IIC_SDA_LO;
  IIC_delay_us(2);
  IIC_SCL_LO; 
  IIC_delay_us(2);
}

void IIC_Stop(void)//停止IIC接口
{
    SDA_OUT();
    IIC_SCL_LO;
    IIC_SDA_LO;
    IIC_delay_us(2);
    IIC_SCL_HI;
    IIC_SDA_HI;
    IIC_delay_us(2);                                
}

void IIC_NAck(void)//非应答信号
{
  IIC_SCL_LO;
  SDA_OUT();
  IIC_delay_us(2);
  IIC_SDA_HI;
  IIC_delay_us(2);
  IIC_SCL_HI;
  IIC_delay_us(2);
  IIC_SCL_LO;  
}

void IIC_Ack(void)//应答信号
{
  IIC_SCL_LO;
  SDA_OUT();
  IIC_SDA_LO;
  IIC_delay_us(2);
  IIC_SCL_HI;
  IIC_delay_us(2);
  IIC_SCL_LO;
}

void IIC_SendByte(uint dat)//送入字节
{
    uchar i;
    SDA_OUT();
    for(i=0;i<8;i++)
    {
        if(dat&0x80) 
                  IIC_SDA_HI;
                else IIC_SDA_LO;
        dat<<=1;
        IIC_delay_us(2);
        IIC_SCL_HI;
        IIC_delay_us(2);
        IIC_SCL_LO;
    }
       IIC_NAck();

}
uchar IIC_ReadByte(uchar ack)//读出字节
{
    uchar i,receive=0;
    SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
    {
        IIC_SCL_LO; 
        IIC_delay_us(0);
        IIC_SCL_HI;
        receive<<=1;
        if(READ_SDA())receive++;   
        IIC_delay_us(0); 
    }
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK
    return receive;
}

void I2C_WriteByte(uchar DiviceID ,uchar address,uchar thedata)
{
    IIC_Start();        //
    IIC_SendByte(DiviceID);//写<<1
    IIC_SendByte(address);  //
    IIC_SendByte(thedata);  //
    IIC_Stop();
}

uchar I2C_ReadByte(uchar  DiviceID ,uchar address)
{
    uchar ret = 100;
    IIC_Start();        
    IIC_SendByte((DiviceID));   //先写寄存器的地址再读<<1
    IIC_SendByte(address);//写寄存器地址
    IIC_Start();
    IIC_SendByte((DiviceID)|1);//读寄存器<<1
    ret = IIC_ReadByte(0);
    IIC_Stop();
    return ret;
}
void I2C_ReadNByte(uchar DiviceID ,uchar address,uchar n,uchar* data)
{
    uchar i;
    IIC_Start();        
    IIC_SendByte((DiviceID));   //先写寄存器的地址再读<<1
    IIC_SendByte(address);//写寄存器地址
    IIC_Start();
    IIC_SendByte((DiviceID)|1);//读寄存器<<1
    for(i=0;i<n-1;i++)
      data[i] = IIC_ReadByte(1);
    data[i] = IIC_ReadByte(0);//最后一个数据发送NACK
    IIC_Stop();
}

PCA9685驱动函数

#include "iic.h"

#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09


void delayms(uint z)
{
  uint x,y;
  for(x=z;x>0;x--)
      for(y=148;y>0;y--);
}

void PCA9685_write(uint address, uint data)//address:数据地址 data:写入的数据参数
{
  IIC_Init();
  IIC_Start();
  IIC_SendByte(0x80);//硬件地址
  IIC_SendByte(address);
  IIC_SendByte(data);
  IIC_Stop();
}

void AngleSet(uint num, uint on, uint off)//参照PCA9685手册,一个输出口用四个8位定义
{
  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);
}

/*---------------------------------------------------------------
                                        PCA9685修改频率函数
----------------------------------------------------------------*/
void setPWMFreq(float freq) 
{
  uint prescale,oldmode=0x00,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(0x00);
  newmode = (oldmode&0x7F) | 0x10; // sleep
  PCA9685_write(0x00, newmode); // go to sleep
  PCA9685_write(0xfe, prescale); // set the prescaler
  PCA9685_write(0x00, oldmode);
  delayms(2);
  PCA9685_write(0x00, oldmode | 0xa1); //10100001
}
//PCA9685_write(0x00, 0x00);//PCA9685初始化
 // AngleSet(1,0,615);//0度值,
//  AngleSet(0,0,2048);//180度值
//  AngleSet(2,0,1332);//90度值
//}

主函数

#include <msp430.h>
#include "iic.h"


void main()
{
     WDTCTL = WDTPW + WDTHOLD;            //关看门狗
     int num=0;
     PCA9685_write(0x00, 0x00);
         //初始化控制板
     while(1)
     {
       for(num=0;num<8;num++)
       {
         AngleSet(num,0,1332);//90度值
         if(num==7)
           num=0;
       }
     }

}

//void main(void)//频闪
//{
//      WDTCTL = WDTPW + WDTHOLD;                  // 看门狗
//      P8DIR |= 0x01;                             // P1.0 输出
//      TBCCTL0 = CCIE;                            // CCR0 中断使能
//      TBCCR0 = 50000;                            // CCR0配置初始值
//      TBCTL = TBSSEL_2 + TACLR;                  // SMCLK, 清除为1
//      TBCTL |= MC_3;
//      _BIS_SR(LPM0_bits + GIE);                  // 进入低功耗0
//}
//
///****** Timer B0 中断服务程序*******/
//
//#pragma vector=TIMERB0_VECTOR
//__interrupt void Timer_B (void)
//{
//        P8OUT ^= 0x01;                            //反转LED1
//        TBCCR0 += 50000;                          // 增加定时偏移量
//}

猜你喜欢

转载自blog.csdn.net/qq_24182661/article/details/81215252