再写一个149与pca9685通信的程序,但是不好用,测出了应答信号但是没有pWM输出,程序如下,请各位指点
#include <msp430x14x.h>
#include<jingzhen8.h>
//===========================延时函数===================================
#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long int
#define SDA_1 P3OUT |= BIT3
#define SDA_0 P3OUT &= ~BIT3
#define SCL_1 P3OUT |= BIT2
#define SCL_0 P3OUT &= ~BIT2
#define DIR_IN P3DIR &= ~BIT3;
#define DIR_OUT P3DIR |= BIT3;
#define SDA_IN ((P3IN>>3)&0x01)
#define PCA9685_adrr 0x80 // 1+A5+A4+A3+A2+A1+A0+w/r
#define PCA9685_SUBADR1 0x02
#define PCA9685_SUBADR2 0x03
#define PCA9685_SUBADR3 0x04
#define PCA9685_MODE1 0x00
#define PCA9685_PRESCALE 0xFE
#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09
#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD
#define SERVOMIN 115 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 590 // this is the 'maximum' pulse length count (out of 4096)
#define SERVO000 130 //0度对应4096的脉宽计数值
#define SERVO180 520 //180度对应4096的脉宽计算值,四个值可根据不同舵机修改
//============================端口初始化=====================
void I2C_init(void)
{
P3SEL=0x00;
P3DIR |= BIT2+BIT3+BIT4; //输出
P3OUT |= BIT4;
}
void init()
{
SDA_1; //sda scl使用前总是被拉高
delay_us(6);
SCL_1;
delay_us(6);
}
//==================IIC起始======================
void I2C_Start() //两拉高延时再分别拉低
{
DIR_OUT;
SDA_1; //发送起始条件的数据信号
delay_us(6); //起始条件建立时间大于4.7us,延时
SCL_1;
delay_us(6); //起始条件建立时间大于4.7us,延时
SDA_0; //发送起始信号
delay_us(6); //起始条件建立时间大于4us,延时
SCL_0; //钳住I2C总线准备发送或接收数据
delay_us(6);
}
//==================IIC停止======================
void I2C_Stop() //SDA为低突然拉高SCL再拉高SDA
{
DIR_OUT;
SDA_0; //发送结束条件的数据信号
delay_us(6);
SCL_1; //发送结束条件的时钟信号
delay_us(6); //结束条件建立时间大于4us,延时
SDA_1; //发送I2C总线结束信号
delay_us(6);
}
//==============================应答信号=========================
void ACK_test()
{
uchar i=0;
SDA_1;
delay_us(6);
SCL_1;
delay_us(6);
DIR_IN;
while((SDA_IN)&&(i<255))
i++;
if (i<255)
{P3OUT &= ~BIT4;}
SCL_0;
delay_us(6);
}
void read_ACK()
{
DIR_OUT;
SDA_0;
delay_us(6);
SCL_1;
delay_us(6);
SCL_0;
delay_us(6);
SDA_1;
}
void read_noACK()
{
DIR_OUT;
SDA_1;
delay_us(6);
SCL_1;
delay_us(6);
SCL_0;
delay_us(6);
SDA_0;
delay_us(6);
}
//====================写8位数=============================
void write_byte(uchar byte)
{
uchar i,temp;
temp=byte;
for(i=0;i<8;i++)
{
SCL_0;
delay_us(6);
if((temp<<i)&0x80)
{
SDA_1;
}
else
{
SDA_0;
}
delay_us(6);
SCL_1;
delay_us(6);
}
SCL_0;
delay_us(6);
}
//===============读8位数========================
uchar read_byte()
{
uchar i,j,k;
SCL_0;
delay_us(6);
SDA_1;
delay_us(6);
DIR_IN;
for(i=0;i<8;i++)
{
delay_us(6);
SCL_1;
delay_us(6);
if(SDA_IN)
{
j=1;
}
else j=0;
k=(k<< 1)|j;
SCL_0;
}
delay_us(6);
return k;
}
//==============写寄存器=============================
void PCA9685_write(uchar address,uchar date)
{
I2C_Start();
write_byte(PCA9685_adrr); //PCA9685的片选地址
ACK_test();
write_byte(address); //写地址控制字节
ACK_test();
write_byte(date); //写数据
ACK_test();
I2C_Stop();
}
//====================读寄存器===============================
uchar PCA9685_read(uchar address)
{
uchar date;
I2C_Start();
write_byte(PCA9685_adrr); //PCA9685的片选地址
ACK_test();
write_byte(address);
ACK_test();
I2C_Start();
write_byte(PCA9685_adrr|0x01); //地址的第八位控制数据流方向,就是写或读
ACK_test();
date=read_byte();
read_noACK();
I2C_Stop();
return date;
}
//==========================复位PCA9685==========================
void reset(void)
{
PCA9685_write(PCA9685_MODE1,0x00);
}
//========================设置频率==========================
void setPWMFreq(float freq)
{
uint prescale,oldmode,newmode;
float prescaleval;
freq *= 0.92; // Correct for overshoot in the frequency setting
prescaleval = 25000000;
prescaleval /= 4096;
prescaleval /= freq;
prescaleval -= 1;
prescale=(int)(prescaleval + 0.5)/1;
oldmode = PCA9685_read(PCA9685_MODE1);
newmode = (oldmode&0x7F) | 0x10; // sleep
PCA9685_write(PCA9685_MODE1, newmode); // go to sleep
PCA9685_write(PCA9685_PRESCALE, prescale); // set the prescaler
PCA9685_write(PCA9685_MODE1, oldmode);
delay_ms(2);
PCA9685_write(PCA9685_MODE1, oldmode | 0xa1);
}
//===========================设置旋转角度============================
void setPWM(uint num, uint on, uint off)
{
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);
}
//===========================主函数==============================
void main()
{
WDTCTL = WDTPW + WDTHOLD;//关闭看门狗
jingzhen8(); //晶振8MZ
I2C_init(); //初始化PCA9685引脚
init();
reset(); //初始化PCA9685
setPWMFreq(50); //设置频率50HZ
while(1)
{
setPWM(0, 0, SERVOMIN);//第0路舵机转到最小角度
setPWM(1, 0, SERVO000);//第1路舵机转到0角度
}
}
此帖出自
小平头技术问答
解决了,待会重新写个贴,一直忘了
一周热门 更多>