#include "reg52.h"
#include "my.h"
#include "intrins.h"
#include "math.h"
#define delayms(n) I2CDelay()
#define I2CDelay() {_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
/* 产生总线起始信号 */
void I2CStart()
{
I2C_SDA = 1; //首先确保SDA、SCL都是高电平
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 0; //先拉低SDA
I2CDelay();
I2C_SCL = 0; //再拉低SCL
}
/* 产生总线停止信号 */
void I2CStop()
{
I2C_SCL = 0; //首先确保SDA、SCL都是低电平
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1; //先拉高SCL
I2CDelay();
I2C_SDA = 1; //再拉高SDA
I2CDelay();
}
void IIC_Ack(void)
{
I2C_SCL=0;
I2C_SDA=0;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SCL=0;
}
/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit I2CWrite(unsigned char dat)
{
bit ack; //用于暂存应答位的值
unsigned char mask; //用于探测字节内某一位值的掩码变量
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{
if ((mask&dat) == 0) //该位的值输出到SDA上
I2C_SDA = 0;
else
I2C_SDA = 1;
I2CDelay();
I2C_SCL = 1; //拉高SCL
I2CDelay();
I2C_SCL = 0; //再拉低SCL,完成一个位周期
}
// I2C_SDA = 1; //8位数据发送完后,主机释放SDA,以检测从机应答
// I2CDelay();
// I2C_SCL = 1; //拉高SCL
// ack = I2C_SDA; //读取此时的SDA值,即为从机的应答值
// I2CDelay();
// I2C_SCL = 0; //再拉低SCL完成应答位,并保持住总线
return 0;//(~ack); //应答值取反以符合通常的逻辑:
//0=不存在或忙或写入失败,1=存在且空闲或写入成功
}
/* I2C总线读操作,并发送非应答信号,返回值-读到的字节 */
unsigned char I2CReadNAK()
{
unsigned char mask;
unsigned char dat;
I2C_SDA = 1; //首先确保主机释放SDA
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{
I2CDelay();
I2C_SCL = 1; //拉高SCL
if(I2C_SDA == 0) //读取SDA的值
dat &= ~mask; //为0时,dat中对应位清零
else
dat |= mask; //为1时,dat中对应位置1
I2CDelay();
I2C_SCL = 0; //再拉低SCL,以使从机发送出下一位
}
I2C_SDA = 1; //8位数据发送完后,拉高SDA,发送非应答信号
I2CDelay();
I2C_SCL = 1; //拉高SCL
I2CDelay();
I2C_SCL = 0; //再拉低SCL完成非应答位,并保持住总线
return dat;
}
/* I2C总线读操作,并发送应答信号,返回值-读到的字节 */
unsigned char I2CReadACK()
{
unsigned char mask;
unsigned char dat;
I2C_SDA = 1; //首先确保主机释放SDA
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{
I2CDelay();
I2C_SCL = 1; //拉高SCL
if(I2C_SDA == 0) //读取SDA的值
dat &= ~mask; //为0时,dat中对应位清零
else
dat |= mask; //为1时,dat中对应位置1
I2CDelay();
I2C_SCL = 0; //再拉低SCL,以使从机发送出下一位
}
I2C_SDA = 0; //8位数据发送完后,拉低SDA,发送应答信号
I2CDelay();
I2C_SCL = 1; //拉高SCL
I2CDelay();
I2C_SCL = 0; //再拉低SCL完成应答位,并保持住总线
return dat;
}
void PCA9685_write(unsigned char address,unsigned char date)
{
I2CStart();
I2CWrite(PCA9685_adrr); //PCA9685?????
IIC_Ack();
I2CWrite(address); //???????
IIC_Ack();
I2CWrite(date); //???
IIC_Ack();
I2CStop();
}
unsigned char PCA9685_read(unsigned char address)
{
unsigned char date;
I2CStart();
I2CWrite(PCA9685_adrr); //PCA9685?????
IIC_Ack();
I2CWrite(address);
IIC_Ack();
I2CStart();
I2CWrite(PCA9685_adrr|0x01); //?????????????,?????
IIC_Ack();
date=I2CReadNAK();
I2CStop();
return date;
}
/*---------------------------------------------------------------
PCA9685??
----------------------------------------------------------------*/
void reset(void)
{
PCA9685_write(PCA9685_MODE1,0x0);
}
void begin(void)
{
reset();
}
void setPWMFreq(double freq)
{
unsigned int prescale,oldmode,newmode;
double 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(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);
delayms(2);
PCA9685_write(PCA9685_MODE1, oldmode | 0xa1);
}
void setPWM(unsigned int num, unsigned int on, unsigned int off)
{
PCA9685_write(LED0_ON_L+4*num,on&0xff);
PCA9685_write(LED0_ON_H+4*num,on>>8);
PCA9685_write(LED0_OFF_L+4*num,off&0xff);
PCA9685_write(LED0_OFF_H+4*num,off>>8);
}
void set_PWM(unsigned char num,double angle)
{
unsigned int a;
angle /= 90;
angle += 0.5;
a = (unsigned int)(angle*4096/20);
setPWM(num,0,a);
}
void main(void)
{
unsigned char i,j;
begin();
setPWMFreq(50);
set_PWM(0,150);
set_PWM(1,150);
set_PWM(2,150);
set_PWM(3,150);
set_PWM(4,150);
set_PWM(5,150);
set_PWM(6,150);
while(1)
{
set_PWM(0,150); set_PWM(3,150);
// setPWM(3,1,800);
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
set_PWM(0,2); set_PWM(3,10);
// setPWM(3,1,100);
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
for(i=1;i;i++) for(j=1;j;j++)I2CDelay();
}
}