1359|0

2015

帖子

0

TA的资源

纯净的硅(中级)

楼主
 

单片机 MSP430 IIC控制器编程(2) [复制链接]

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

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


iic.h

[cpp] view plain copy
#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

[cpp] view plain copy
#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

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表