使用AVR控制PCA9685输出PWM型号,硬件调试没问题的话却一直无法输出信号,求大佬帮忙看看
时间:10-02
整理:3721RD
点击:
附上自己写的程序:
#include "avr/io.h"
#include "avr/interrupt.h"
#include "avr/signal.h"
#include "avr/delay.h"
#define Start() ( TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) ) //产生START信号
#define Stop() ( TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN) ) //产生STOP信号
#define PCA9685_adrr 0x80
#define PCA9685_MODE1 0x0
#define PCA9685_PRESCALE 0xfe
//#define on 0
#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9
#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD
#define uint unsigned int
#define uchar unsigned char
void TWI_write( unsigned char twi_d )
{
TWDR = ( twi_d );
TWCR = ( 1<<TWINT ) | ( 1<<TWEN );
}
void TWI_init( void )
{
TWCR=0X00; //关闭TWI总线
TWBR=0x12; //设置传输比特率
TWSR=0x03; //设置TWI总线的速度,频率不能大于400K,否则5767不工作
TWCR=0x04; //使能TWI总线
}
unsigned char TWI_read( void )
{
unsigned char temp;
TWCR |= 0x04;
while(!(TWCR&(1<<TWINT)));
temp = TWDR;
return temp;
}
void PCA_Write(uchar address,uchar date)
{
Start();
while(!(TWCR&(1<<TWINT)));
TWI_write( PCA9685_adrr );
while(!(TWCR&(1<<TWINT)));
TWI_write( address );
while(!(TWCR&(1<<TWINT)));
TWI_write( date );
while(!(TWCR&(1<<TWINT)));
Stop();
}
uchar PCA_Read(uchar address)
{
uchar date;
Start();
while(!(TWCR&(1<<TWINT)));
TWI_write( PCA9685_adrr );
while(!(TWCR&(1<<TWINT)));
TWI_write( address );
while(!(TWCR&(1<<TWINT)));
TWI_write(PCA9685_adrr|0x01); //地址的第八位控制数据流方向,就是写或读
date = TWI_read();
Stop();
return date;
}
void reset(void)
{
PCA_Write(PCA9685_MODE1,0x0);
}
void begin(void)
{
reset();
}
void setPWMFreq(float freq)
{
unsigned int prescale,oldmode,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 = PCA_Read(PCA9685_MODE1);
newmode = (oldmode&0x7F) | 0x10; // sleep
PCA_Write(PCA9685_MODE1, newmode); // go to sleep
PCA_Write(PCA9685_PRESCALE, prescale); // set the prescaler
oldmode &= 0xef; //清除sleep位
PCA_Write(PCA9685_MODE1, oldmode);
//delayms(2);
//Delay_1ms();
_delay_ms(2);
PCA_Write(PCA9685_MODE1, oldmode | 0xA1);
}
/****************************************************************************
PCA9685修改角度函数
num:舵机PWM输出引脚0~15,on:PWM上升计数值0~4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。
****************************************************************************/
//offzhuomian
void SetPWM(unsigned int num, unsigned int on, unsigned int off)
{
PCA_Write(LED0_ON_L+4*num,on);
PCA_Write(LED0_ON_H+4*num,on>>8);
PCA_Write(LED0_OFF_L+4*num,off);
PCA_Write(LED0_OFF_H+4*num,off>>8);
}
void main()
{
DDRC = 0x80; //scl输出,sda输入
//PORTC
TWBR = 0x12; //设置输出比特率
TWSR = 0x03; //设置TWI总线速度
TWCR = 0x04; //使能TWI
begin();
setPWMFreq(60); //Freq50HZ
SetPWM(0,0,2048);
}
#include "avr/io.h"
#include "avr/interrupt.h"
#include "avr/signal.h"
#include "avr/delay.h"
#define Start() ( TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) ) //产生START信号
#define Stop() ( TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN) ) //产生STOP信号
#define PCA9685_adrr 0x80
#define PCA9685_MODE1 0x0
#define PCA9685_PRESCALE 0xfe
//#define on 0
#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9
#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD
#define uint unsigned int
#define uchar unsigned char
void TWI_write( unsigned char twi_d )
{
TWDR = ( twi_d );
TWCR = ( 1<<TWINT ) | ( 1<<TWEN );
}
void TWI_init( void )
{
TWCR=0X00; //关闭TWI总线
TWBR=0x12; //设置传输比特率
TWSR=0x03; //设置TWI总线的速度,频率不能大于400K,否则5767不工作
TWCR=0x04; //使能TWI总线
}
unsigned char TWI_read( void )
{
unsigned char temp;
TWCR |= 0x04;
while(!(TWCR&(1<<TWINT)));
temp = TWDR;
return temp;
}
void PCA_Write(uchar address,uchar date)
{
Start();
while(!(TWCR&(1<<TWINT)));
TWI_write( PCA9685_adrr );
while(!(TWCR&(1<<TWINT)));
TWI_write( address );
while(!(TWCR&(1<<TWINT)));
TWI_write( date );
while(!(TWCR&(1<<TWINT)));
Stop();
}
uchar PCA_Read(uchar address)
{
uchar date;
Start();
while(!(TWCR&(1<<TWINT)));
TWI_write( PCA9685_adrr );
while(!(TWCR&(1<<TWINT)));
TWI_write( address );
while(!(TWCR&(1<<TWINT)));
TWI_write(PCA9685_adrr|0x01); //地址的第八位控制数据流方向,就是写或读
date = TWI_read();
Stop();
return date;
}
void reset(void)
{
PCA_Write(PCA9685_MODE1,0x0);
}
void begin(void)
{
reset();
}
void setPWMFreq(float freq)
{
unsigned int prescale,oldmode,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 = PCA_Read(PCA9685_MODE1);
newmode = (oldmode&0x7F) | 0x10; // sleep
PCA_Write(PCA9685_MODE1, newmode); // go to sleep
PCA_Write(PCA9685_PRESCALE, prescale); // set the prescaler
oldmode &= 0xef; //清除sleep位
PCA_Write(PCA9685_MODE1, oldmode);
//delayms(2);
//Delay_1ms();
_delay_ms(2);
PCA_Write(PCA9685_MODE1, oldmode | 0xA1);
}
/****************************************************************************
PCA9685修改角度函数
num:舵机PWM输出引脚0~15,on:PWM上升计数值0~4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。
****************************************************************************/
//offzhuomian
void SetPWM(unsigned int num, unsigned int on, unsigned int off)
{
PCA_Write(LED0_ON_L+4*num,on);
PCA_Write(LED0_ON_H+4*num,on>>8);
PCA_Write(LED0_OFF_L+4*num,off);
PCA_Write(LED0_OFF_H+4*num,off>>8);
}
void main()
{
DDRC = 0x80; //scl输出,sda输入
//PORTC
TWBR = 0x12; //设置输出比特率
TWSR = 0x03; //设置TWI总线速度
TWCR = 0x04; //使能TWI
begin();
setPWMFreq(60); //Freq50HZ
SetPWM(0,0,2048);
}
顶一个!