您的位置:首页 > 编程语言

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

2015-11-21 10:11 405 查看
直接附上最近调试成功的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息