关闭

单片机 MSP430 IIC控制器编程(2)

标签: 微型投影仪单片机
546人阅读 评论(0) 收藏 举报
分类:

直接附上最近调试成功的IIC控制器程序,只贴出IIC模块,因为程序最主要的东西就是IIC通信了,其次是那些参数的设置。

这个程序暂时还比较简单,因为项目还才做到一半。


iic.h

#include "utils.h"

#ifndef __IIC_H__
#define __IIC_H__

void iic_master_init(uint8 slave_address);

int8 iic_write_register_data(uint8 slave_address, uint8 reg_address, uint8 *data, uint8 data_len);

int8 iic_read_register_one_byte(uint8 slave_address, uint8 reg_address, uint8 *data);



#endif /* end of iic.h */


iic.h

#include "iic.h"
#include "uart.h"

#define MASTER_USE_NO_INTERRUPT

void iic_master_init(uint8 slave_address)
{
    //Assign I2C pins to USCI_B0    P3.1 IIC_SDA   P3.2 IIC_SCL
    P3SEL |= 0x06;					                //选择USCI模式
    UCB0CTL1 |= UCSWRST;                            //置位UCSWRST, 使得USCI处于复位状态
    UCB0CTL0 |= UCMST + UCMODE_3 + UCSYNC;          //主控, I2C, 同步模式
    UCB0CTL1 |= UCSSEL_2 + UCSWRST;                 // Use SMCLK
    UCB0BR0 = 240;                                  // fSCL = SMCLK/240 = 100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = (slave_address >> 1);                      // Slave Address
    UCB0CTL1 &= ~UCSWRST;                           // Clear SW reset, resume operation
}

static void iic_slave_init(uint8 self_address)
{
    //Assign I2C pins to USCI_B0    P3.1 IIC_SDA   P3.2 IIC_SCL
    P3SEL |= 0x06;					                //选择USCI模式
    UCB0CTL1 |= UCSWRST;                            //置位UCSWRST, 使得USCI处于复位状态
    UCB0CTL0 &= ~UCMST;                             //受控
    UCB0CTL0 |= UCMODE_3 + UCSYNC;                  //I2C, 同步模式

    UCB0I2COA = self_address;                       // self address
    UCB0CTL1 &= ~UCSWRST;                           // Clear SW reset, resume operation
}

static uint8 iic_is_busy(void)
{
    uint8 busy = UCB0STAT & UCBBUSY;                //0, idle; 1, busy
    return !!busy;
}


#ifdef MASTER_USE_NO_INTERRUPT
static void iic_master_set_writemode(void)
{
    UCB0CTL1 |= UCTR;                               //发送器
    IFG2 &= ~UCB0TXIFG;                             //清除发送中断标志
    IE2 &= ~UCB0RXIE;                               // Disable RX interrupt
    IE2 &= ~UCB0TXIE;                               // Disable TX interrupt
}

static void iic_master_set_readmode(void)
{
    UCB0CTL1 &= ~UCTR;                              //接收器
    IFG2 &= ~UCB0RXIFG;                             //清除接收中断标志
    IE2 &= ~UCB0TXIE;                               // Disable TX interrupt
    IE2 &= ~UCB0RXIE;                               // Disable RX interrupt
}



//===========================================

static int8 iic_master_send_multibyte_start_timeout(uint32 time_out)
{
    volatile uint32 timeout = 0;
    //发送起始信号
    UCB0CTL1 |= UCTXSTT;

    timeout = time_out;
    //起始信号产生后,TXIFG会被置位,此时从器件已经对地址作出应答(可以再判断UCTXSTT是否被清零)
    while(!(IFG2 & UCB0TXIFG) && (--timeout))
    {
        //PutChar('x');
    }
    if(timeout == 0)
    {
        return __TIMEOUT;                                       //超时
    }

    IFG2 &= ~UCB0TXIFG;                                         //清除发送中断标志

    return __OK;
}

static int8 iic_master_send_multibyte_next_timeout(uint8 tx_data, uint32 time_out)
{
    volatile uint32 timeout = 0;

    //先发送一个字节数据
    UCB0TXBUF = tx_data;

    timeout = time_out;
    //等待该字节发送完毕
    while(!(IFG2 & UCB0TXIFG) && (--timeout))
    {
        //PutChar('x');
    }
    if(timeout == 0)
    {
        return __TIMEOUT;                                       //超时
    }

    IFG2 &= ~UCB0TXIFG;                                         //清除发送中断标志

    return __OK;
}

static int8 iic_master_send_multibyte_finish_timeout(uint8 tx_data, uint32 time_out)
{

    iic_master_send_multibyte_next_timeout(tx_data, time_out);

    //发送停止信号
    UCB0CTL1 |= UCTXSTP;

    return __OK;
}

static void iic_master_send_multibyte_stop(void)
{
    //发送停止信号
    UCB0CTL1 |= UCTXSTP;

}

//==================================================

static int8 iic_master_recv_multibyte_start_timeout(uint32 time_out)
{
    volatile uint32 timeout = 0;

    //Send start condition, and master device will send slave_address to slave device
    UCB0CTL1 |= UCTXSTT;

    timeout = time_out;
    //从器件已经对地址作出应答,UCTXSTT就被清零
    while((UCB0CTL1 & UCTXSTT) && (--timeout))
    {
        //PutChar('x');
    }
    if(timeout == 0)
    {
        return __TIMEOUT;                                     //超时
    }

    return __OK;
}

static int8 iic_master_recv_multibyte_next_timeout(uint8 *rx_data, uint32 time_out)
{
    volatile uint32 timeout = 0;

    timeout = time_out;
    // Wait for RX buffer
    while((!(IFG2 & UCB0RXIFG)) && (--timeout))
    {
        //PutChar('x');
    }

    if(timeout == 0)
    {

        return __TIMEOUT;
    }
    IFG2 &= ~UCB0RXIFG;

    //Capture data from receive buffer after setting stop bit due to
    //MSP430 I2C critical timing.
    *rx_data = UCB0RXBUF;

    return __OK;
}



static int8 iic_master_recv_multibyte_finish_timeout(uint8 *rx_data, uint32 time_out)
{
    volatile uint32 timeout = 0;

    //发送停止信号
    UCB0CTL1 |= UCTXSTP;

    timeout = time_out;
    //等待停止信号发送成功: 主机在接收完最后一个字节后,就发起停止信号,从机停止向主机发送数据
    while((UCB0CTL1 & UCTXSTP) && (--timeout))
    {
        //PutChar('x');
    }

    if(timeout == 0)
    {
        return __TIMEOUT;
    }

    timeout = time_out;
    // Wait for RX buffer
    while((!(IFG2 & UCB0RXIFG)) && (--timeout))
    {
        //PutChar('x');
    }

    if(timeout == 0)
    {

        return __TIMEOUT;
    }
    IFG2 &= ~UCB0RXIFG;

    //Capture data from receive buffer after setting stop bit due to
    //MSP430 I2C critical timing.
    *rx_data = 0x00;
    *rx_data = UCB0RXBUF;

    return __OK;
}

static void iic_master_recv_multibyte_stop(void)
{
    //发送停止信号
    UCB0CTL1 |= UCTXSTP;
}


#endif  /* end of MASTER_USE_NO_INTERRUPT */



//===================================================
int8 iic_write_register_data(uint8 slave_address, uint8 reg_address, uint8 *data, uint8 data_len)
{
    uint8 i = 0;
    int8 ret = __OK;

    Printf("0000\n");

    iic_master_init(slave_address);

    //检测IIC总线是否繁忙
    while( iic_is_busy() == 1)
    {
        ;
    }

    //设置发送模式
    iic_master_set_writemode();

    //开始一次数据传输:先发送寄存器地址
    ret = iic_master_send_multibyte_start_timeout(100);
    if(ret == __TIMEOUT)
    {
        iic_master_send_multibyte_stop();
        Printf("1111\n");
        return ret;
    }

    ret= iic_master_send_multibyte_next_timeout(reg_address, 1000);
    if(ret == __TIMEOUT)
    {
        iic_master_send_multibyte_stop();
        Printf("2222\n");
        return ret;
    }

    for(i = 0; i < data_len; i++)
    {
        ret= iic_master_send_multibyte_next_timeout(*(data + i), 1000);
        if(ret == __TIMEOUT)
        {
            iic_master_send_multibyte_stop();
            Printf("3333\n");
            return ret;
        }
    }

    iic_master_send_multibyte_stop();


    Printf("4444\n");

    return __OK;
}

#if 1
int8 iic_read_register_one_byte(uint8 slave_address, uint8 reg_address, uint8 *data)
{

    int8 ret = __OK;

    Printf("0000\n");

    iic_master_init(slave_address);

    Printf("6666\n");
    //检测IIC总线是否繁忙
    while( iic_is_busy() == 1)
    {
        ;
    }

    Printf("7777\n");
    //设置发送模式: 写
    iic_master_set_writemode();

    //发送起始信号和器件地址
    ret = iic_master_send_multibyte_start_timeout(100);
    if(ret == __TIMEOUT)
    {
        iic_master_send_multibyte_stop();
        Printf("1111\n");
        return ret;
    }

    //发送寄存器地址
    ret = iic_master_send_multibyte_next_timeout(reg_address, 1000);
    if(ret == __TIMEOUT)
    {
        iic_master_send_multibyte_stop();
        Printf("2222\n");
        return ret;
    }


    //设置接收模式
    iic_master_set_readmode();

    //发送起始信号和器件地址
    ret = iic_master_recv_multibyte_start_timeout(600000);
    if(ret == __TIMEOUT)
    {
        iic_master_recv_multibyte_stop();
        Printf("3333\n");
        return ret;
    }

    //接收从机发来的一个字节
    ret = iic_master_recv_multibyte_finish_timeout(data, 10000);
    if(ret == __TIMEOUT)
    {
        iic_master_recv_multibyte_stop();
        Printf("5555\n");
        return ret;
    }

    Printf("4444\n");

    return __OK;
}


#else

int8 iic_read_register_one_byte(uint8 slave_address, uint8 reg_address, uint8 *data)
{

    int8 ret = __OK;

    Printf("0000\n");

    iic_master_init(slave_address);

    Printf("6666\n");
    //检测IIC总线是否繁忙
    while( iic_is_busy() == 1)
    {
        ;
    }

    Printf("1212120\n");
    //设置发送模式: 写
    iic_master_set_writemode();

    //开始一次数据传输:先发送寄存器地址
    volatile uint32 timeout = 0;
    //Send start condition.
    UCB0CTL1 |= UCTXSTT;

    timeout = 100;
    //Poll for transmit interrupt flag.
    while(!(IFG2 & UCB0TXIFG) && (--timeout))
    {
        //PutChar('x');
    }
    if(timeout == 0)
    {
        Printf("7777 timeout\n");
        return __TIMEOUT;                                     //超时
    }

    IFG2 &= ~UCB0TXIFG;                             //清除发送中断标志

    //Send single byte data.
    UCB0TXBUF = reg_address;
    Printf("34444\n");

    timeout = 100;
    //Poll for transmit interrupt flag.
    while(!(IFG2 & UCB0TXIFG) && (--timeout))
    {
        //PutChar('x');
    }
    if(timeout == 0)
    {
        Printf("78956 timeout\n");
        return __TIMEOUT;                                     //超时
    }

    IFG2 &= ~UCB0TXIFG;                             //清除发送中断标志


    //设置接收模式
    iic_master_set_readmode();

    //发送起始信号: 读
    UCB0CTL1 |= UCTXSTT;

    timeout = 5000;
    //Poll for transmit interrupt flag.
    while((UCB0CTL1 & UCTXSTT) && (--timeout))
    {
        //PutChar('x');
    }
    if(timeout == 0)
    {
        Printf("3131 timeout\n");
        return __TIMEOUT;                                     //超时
    }

    //Send stop condition.
    UCB0CTL1 |= UCTXSTP;

    timeout = 5000;
    //Wait for Stop to finish
    while((UCB0CTL1 & UCTXSTP) && (--timeout))
    {
        //PutChar('x');
    }

    //Check if transfer timed out
    if(timeout == 0)
    {
        Printf("9990 timeout\n");
        return __TIMEOUT;
    }

    Printf("2244\n");

    timeout = 5000;
    // Wait for RX buffer
    while((!(IFG2 & UCB0RXIFG)) && (--timeout))
    {
        //PutChar('x');
    }

    //Check if transfer timed out
    if(timeout == 0)
    {
        Printf("1234 timeout\n");
        return __TIMEOUT;
    }

    IFG2 &= ~UCB0RXIFG;
    //Capture data from receive buffer after setting stop bit due to
    //MSP430 I2C critical timing.
    *data = UCB0RXBUF;

    Printf("4444\n");

    return __OK;
}

#endif

//======================================================

#ifdef USE_INTERRUPT
void iic_set_writeMode(void)
{
    UCB0CTL1 |= UCTR;                               //发送器
    IFG2 &= UCB0TXIFG;                              //清楚发送中断标志
    IE2 &= ~UCB0RXIE;                               // Disable RX interrupt
    IE2 |= UCB0TXIE;                                // Enable TX interrupt
}

void iic_ReadMode(void)
{
    UCB0CTL1 &= ~UCTR;                              //接收器
    IFG2 &= UCB0RXIFG;                              //清楚接收中断标志
    IE2 &= ~UCB0TXIE;                               // disable TX interrupt
    IE2 |=  UCB0RXIE;                               // enable RX interrupt
}

#endif



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:192068次
    • 积分:3401
    • 等级:
    • 排名:第9846名
    • 原创:135篇
    • 转载:93篇
    • 译文:0篇
    • 评论:82条
    最新评论