MSP430G2553软件实现IIC

相关材料

IIC总线协议
Verilog实现IIC主机对从机的写操作(zybo z7板运行代码)
pca9685的舵机控制

程序框图

单片机IIC控制流程框图
在这里插入图片描述

代码实现

IIC实现代码(前面的宏定义适用于MSP430)

#define uchar unsigned char
#define uint unsigned int
//=====================================延时函数=================================
#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))
//=====================================IIC地址设置=================================
#define  WHO_AM_I         0x75           //IIC地址寄存器(默认数值0x68,只读)--(6050)
#define  SlaveAddress     0x80           //IIC写入时的地址字节数据,+1为读取--(PCA9685)
//=====================================IIC端口定义=================================
#define  SCL1  P1OUT|=BIT4
#define  SCL0  P1OUT&= ~BIT4

#define  SDA1  P1OUT|=BIT5               //IIC数据引脚
#define  SDA0  P1OUT&= ~BIT5
#define  SDAIN  P1DIR&= ~BIT5
#define  SDAOUT  P1DIR|=BIT5
#define  SDADATA  (P1IN&BIT5)
//================================I2C起始信号================================
void I2C_Start()
{
    SDA1;               //拉高数据线
    SCL1;               //拉高时钟线
    delay_us(5);         //延时
    SDA0;               //产生下降沿
    delay_us(5);
    SCL0;               //拉低时钟线
}
//================================I2C停止信号================================
void I2C_Stop()
{
    SDA0;               //拉高数据线
    SCL1;
    delay_us(5);
    SDA1;               //产生上升沿
    delay_us(5);
}
//================================I2C发送应答信号 入口参数:ack (0:ACK 1:NAK)================================
void I2C_SendACK(uchar ack)
{
    SDAOUT;
    if(ack)
        SDA1;
    else
        SDA0;
    //SDA=ack;          //读应答信号
    SCL1;
    delay_us(5);
    SCL0;               //拉低时钟线
    delay_us(5);
}
//================================I2C接收应答信号================================
uchar I2C_RecvACK()
{
    uchar cy;
    SCL1;
    SDAIN;
    delay_us(5);
    if(SDADATA)
    {
        cy=1;
    }
    else
    {
        cy=0;
    }
    //cy=SDA;           //读应答信号
    SCL0;
    delay_us(5);
    SDAOUT;
    return cy;
}
//================================向I2C总线发送一个字节数据================================
void I2C_SendByte(uchar dat)
{
    uchar i;
    for(i=0;i<8;i++)    //8位计数器
    {
        if((dat<<i)&0x80)
        {
            SDA1;
        }
        else
        {
            SDA0;
        }
        //SDA=cy;       //送数据口
        SCL1;
        delay_us(5);
        SCL0;
        delay_us(5);
    }
    I2C_RecvACK();
}
//================================从I2C总线接收一个字节数据================================
uchar I2C_RecvByte()
{
    uchar i;
    uchar dat=0,cy;
    SDA1;               //使能内部上拉,准备读取数据,
    SDAIN;              //8位计数器
    for(i=0;i<8;i++)
    {
        dat<<=1;
        SCL1;
        delay_us(5);
        if(SDADATA)
        {
            cy=1;
        }
        else
        {
            cy=0;
        }
        dat|=cy;        //读数据
        SCL0;
        delay_us(5);
    }
    SDAOUT;
    return dat;
}
//=======================向I2C设备写入一个字节数据======================================
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
    I2C_Start();                        //起始信号
    I2C_SendByte(SlaveAddress);         //发送设备地址+写信号
    I2C_SendByte(REG_Address);          //内部寄存器地址
    I2C_SendByte(REG_data);             //内部寄存器数据
    I2C_Stop();                         //发送停止信号
}
//======================从I2C设备读取一个字节数据=====================================
uchar Single_ReadI2C(uchar REG_Address)
{
    uchar REG_data;

    I2C_Start();                        //起始信号
    I2C_SendByte(SlaveAddress);         //发送设备地址+写信号
    I2C_SendByte(REG_Address);          //发送存储单元地址,从0开始
    I2C_Start();                        //起始信号
    I2C_SendByte(SlaveAddress+1);       //发送设备地址+读信号
    REG_data=I2C_RecvByte();            //读出寄存器数据
    I2C_SendACK(1);                     //接收应答信号
    I2C_Stop();                         //停止信号

    return REG_data;
}
//======================================合成数据======================================
int GetData(uchar REG_Address)
{
    char H,L;
    H=Single_ReadI2C(REG_Address);
    L=Single_ReadI2C(REG_Address+1);
    return (H<<8)+L;                    //合成数据
}

单片机调用程序(对应于pca9685驱动板从机)

设置PWM频率

void setPWMFreq(float freq)
{
                uint prescale,oldmode,newmode;
                float prescaleval;
                freq_re=freq;
                freq *= 0.96;               // 用于纠正频率偏差
                prescaleval = 25000000;
                prescaleval /= 4096;
                prescaleval /= freq;
                prescaleval -= 1;
//                prescale = floor(prescaleval + 0.5);
                prescale=(int)(prescaleval + 0.5 );
                oldmode = Single_ReadI2C(PCA9685_MODE1);
                newmode = (oldmode&0x7F) | 0x10; // sleep
                Single_WriteI2C(PCA9685_MODE1, newmode); //调用之前写的IIC写入函数,go to sleep
                Single_WriteI2C(PCA9685_PRESCALE, prescale); // set the prescaler
                Single_WriteI2C(PCA9685_MODE1, oldmode);
                delay_ms(2);
                Single_WriteI2C(PCA9685_MODE1, oldmode | 0xa1);
}

设置pca9685各个舵机输出寄存器的值

// =========================输出通道设置,占空比设置从0到ON跳成高  再到off跳成低====================================
void setPWM(uint num, uint on, uint off)    //0--4096
{
                Single_WriteI2C(LED0_ON_L+4*num,on);
                Single_WriteI2C(LED0_ON_H+4*num,on>>8);
                Single_WriteI2C(LED0_OFF_L+4*num,off);
                Single_WriteI2C(LED0_OFF_H+4*num,off>>8);
}
// =========================num通道,ms高电平毫秒====================================
void setPWM_ms(uint num,float time_ms)
{
               uint time;
               time=(uint)((time_ms*freq_re/1000)*4096);
               setPWM(num, 0, time) ;
}
/******************************************************************************************************
 * 名       称:setARC()
 * 功       能:设置舵机角度
 * 入口参数:舵机口num,角度arc
 * 出口参数:无
 * 说       明:
 * 范       例:无
 ******************************************************************************************************/
void setARC(uint num,float arc)
{
	float time_ms=arc*2/180+0.5;
	setPWM_ms(num,time_ms);

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值