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

原创 2015年11月21日 10:11:44

直接附上最近调试成功的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



相关文章推荐

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

近日在开发开发微型投影仪的单片机程序,主要是用单片机控制DLP芯片组进行相应的初始化和参数设置,所有芯片的通信接口都是用IIC。 在此记录下,IIC的开发过程。 1.初始化 17.3.1 USCI...

单片机 MSP430 模拟IIC编程(2)

示例 ////////////////////////////////////////////////// void I2C_Master_Init(void) /** * Initializes...

单片机 MSP430 模拟IIC编程(1)

20151121 以下附上的是模拟IIC通信模块程序,是我在TI官网提供的投影仪评估板例程中拿出来的,本人还没有验证,暂且认为他可以工作,估计下个星期就会去验证他,到时候再修改。 其实贴出这个程序...

msp430f149单片机模拟IIC驱动OLED

  • 2014年07月24日 14:55
  • 32KB
  • 下载

GSM/GPRS模块 AT指令集C语言编程——基于有方M660+和MSP430单片机

GSM/GPRS芯片是手机中负责收发短信、拨打电话以及访问GPRS网络的核心器件。有方M660+为深圳有方公司生产的一款超小封装的GSM/GPRS工业无线模块,可以提供高品质的语音、短信、数据业务等功...
  • jzj1993
  • jzj1993
  • 2013年09月23日 14:51
  • 7970

MSP430 IIC通信

#include #define OP_READ 0xa1 //器件地址读 #define OP_WRITE 0xa0 //...

Proteus中MSP430与SHT11的IIC通信问题

调了两天,MSP430始终接收不到数据,一直以为是代码的问题,今天无意中看到别人的一片文章,才发现问题出在上拉电阻上。DATA线的上拉电阻不能太大,10k不行,换成了1k就没问题了。mark一下,顺便...

自制BSL编程MSP430单片机

  • 2012年07月28日 03:57
  • 1021KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:单片机 MSP430 IIC控制器编程(2)
举报原因:
原因补充:

(最多只允许输入30个字)