1697|0

3836

帖子

19

TA的资源

纯净的硅(中级)

楼主
 

MSP430F5529硬件IIC代码 [复制链接]


读有个小问题,最后总会多读一位。
是由必须在接受最后一个数据之前发送停止和NACK,而我把这个发送放在中断里的(放我的发送函数里会出现一些问题),数据进缓冲器在进中断服务程序前,所以会多读一个。但是不影响,我后面已做处理,不管最后一个字符。
/****************************************************************IIC_device.c*********************************************************************************************************/
#include "IIC_device.h"
#include "Delay.h"

extern unsigned char RXByteCtr;
extern unsigned char TXByteCtr;
extern unsigned char TxData[10];
extern unsigned char RxBuf[10];

void iic_init(uint8_t SLAVE_ADDRESS)
{
        //Assign I2C pins to USCI_B0    P3.0 IIC_SDA   P3.1 IIC_SCL
        P3SEL |= 0x03;
        UCB0CTL1 |= UCSWRST;                      // Enable SW reset
        UCB0CTL0 |= UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
        UCB0CTL1 |= UCSSEL_2 + UCSWRST;            // Use SMCLK
        UCB0BR0 = 240;                            // fSCL = SMCLK/240 = 100kHz
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDRESS;                // Slave Address
        UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
}
void iic_WriteMode(void)
{
    UCB0CTL1 |= UCTR;
    USCI_B_I2C_clearInterrupt(USCI_B0_BASE,USCI_B_I2C_TRANSMIT_INTERRUPT);
    UCB0IE &= ~UCRXIE;                        // Disable RX interrupt
    UCB0IE |= UCTXIE;                         // Enable TX interrupt
}
void iic_ReadMode(void)
{
    UCB0CTL1 &=~ UCTR;
    USCI_B_I2C_clearInterrupt(USCI_B0_BASE,USCI_B_I2C_RECEIVE_INTERRUPT);
    UCB0IE &= ~UCTXIE;                        // Disable TX interrupt
    UCB0IE |= UCRXIE;                         // Enable RX interrupt
}
void iic_writebyte(uint8_t reg_address,uint8_t write_number,uint8_t *data_to_write)
{
    uint8_t i=0;
    while(UCB0STAT & UCBBUSY);
    iic_WriteMode();
    TxData[write_number]=reg_address;
    for(i=write_number;i>0;i--)
    {
        TxData[i-1]= *data_to_write++;
    }
    TXByteCtr=write_number+1;            // Load TX byte counter
    UCB0CTL1 |= UCTXSTT;                 // I2C TX, start condition
    while (UCB0CTL1 & UCTXSTP);
}
void iic_readbyte(uint8_t reg_address,uint8_t read_number)
{
    while(UCB0STAT & UCBBUSY);
    iic_WriteMode();
    TxData[0]=reg_address;
    TXByteCtr=1;                                    // Load TX byte counter
    UCB0CTL1 |= UCTXSTT;                 // I2C TX, start condition
    while (UCB0CTL1 & UCTXSTP);
    Delay_us(200);
    iic_ReadMode();
    RXByteCtr=read_number;
    UCB0CTL1 |= UCTXSTT;
    while (USCI_B_I2C_getInterruptStatus(USCI_B0_BASE,USCI_B_I2C_RECEIVE_INTERRUPT));
    while (UCB0CTL1 & UCTXSTP);
}


/****************************************************************IIC_device.h*********************************************************************************************************/
#ifndef IIC_DEVICE_H_
#define IIC_DEVICE_H_

#include "MSP430F5529_conf.h"

void iic_init(uint8_t SLAVE_ADDRESS);
void iic_WriteMode(void);
void iic_ReadMode(void);
void iic_writebyte(uint8_t reg_address,uint8_t write_number,uint8_t *data_to_write);
void iic_readbyte(uint8_t reg_address,uint8_t read_number);

#endif /* IIC_DEVICE_H_ */

/*******************************************************************main.c*********************************************************************************************************/
/************************************************************************
* @file        main.c
* @author        Mr.Blue
* @version V1.0
* @date         2015-6-16
* @brief   This file provides functions to manage the functionalities
*                    of the IIC
* @verbatim
************************************************************************/
/******************************INCLUDE**********************************/
#include "MSP430F5529_conf.h"
#include "Delay.h"
#include "IIC_device.h"
/******************************DEFINE***********************************/
#define UCS_MCLK_DESIRED_FREQUENCY_IN_KHZ   24000
//Target frequency for MCLK in kHz
#define UCS_MCLK_FLLREF_RATIO   6
//MCLK/FLLRef Ratio
#define UCS_XT1_TIMEOUT 50000
//Desired Timeout for XT1 initialization
#define UCS_XT2_TIMEOUT 50000
//Desired Timeout for XT2 initialization

#define IIC_SLAVE_ADDRESS 0X50

void UCS_init();
void GPIO_init();
/*****************************VARIABLE**********************************/
u16 status;
//Variable to store status of Oscillator fault flags

unsigned char TXByteCtr=0,RXByteCtr=0;
unsigned char TxData[10]={0};
unsigned char RxBuf[10]={0};

uint8_t data_address=2;
uint8_t data_to_write[10]={'A','B','C','D','E','F','G','H','I','J'};
uint8_t data_to_read[10]={0};
/*******************************MAIN************************************/
int main(void)
{
    u8 j=0;
    WDT_A_hold(WDT_A_BASE);
    UCS_init();
    GPIO_init();
    iic_init(IIC_SLAVE_ADDRESS);
    iic_writebyte(data_address,4,data_to_write);
    Delay_ms(2);                                                                  //EEPROM在读写切换时需要一定延时,亲测读写为4个时至少2MS,读写10个时至少5MS
    iic_readbyte(data_address,4);
    while(1)
    {
        for(j=0;j<=9;j++)
        {
            data_to_read[j]=RxBuf[9-j];
        }
            GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0);
            Delay_ms(500);
    }
}

void UCS_init()
{
        //Set VCore = 3 for 25MHz clock
    PMM_setVCore(PMM_CORE_LEVEL_3 );
    UCS_setExternalClockSource(32768,4000000);

    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN4);
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5,GPIO_PIN5);
    UCS_turnOnLFXT1WithTimeout(UCS_XT1_DRIVE_0,UCS_XCAP_3,UCS_XT1_TIMEOUT);

    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN2);
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5,GPIO_PIN3);
    UCS_turnOnXT2WithTimeout(UCS_XT2_DRIVE_4MHZ_8MHZ,UCS_XT2_TIMEOUT);

    //Select XT1 as ACLK source
    UCS_initClockSignal(UCS_ACLK,UCS_XT1CLK_SELECT,UCS_CLOCK_DIVIDER_1);
    //Select XT2 as FLL reference
        UCS_initClockSignal(UCS_FLLREF,UCS_XT2CLK_SELECT,UCS_CLOCK_DIVIDER_1);
        //Set Ratio and Desired MCLK Frequency  and initialize DCO
        UCS_initFLLSettle(UCS_MCLK_DESIRED_FREQUENCY_IN_KHZ,UCS_MCLK_FLLREF_RATIO);
        //Select DCO as SMCLK source
        UCS_initClockSignal(UCS_SMCLK,UCS_DCOCLK_SELECT,UCS_CLOCK_DIVIDER_1);

    // Enable global oscillator fault flag
    SFR_clearInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);
    SFR_enableInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);

    // Enable global interrupt
    __bis_SR_register(GIE);
}

void GPIO_init()
{
    GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN0);
    GPIO_setAsOutputPin(GPIO_PORT_P4,GPIO_PIN7);
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=UNMI_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(UNMI_VECTOR)))
#endif
void NMI_ISR(void)
{
    do
    {
        // If it still can't clear the oscillator fault flags after the timeout,
        // trap and wait here.
        status = UCS_clearAllOscFlagsWithTimeout(1000);
    }
    while(status != 0);
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_B0_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_B0_VECTOR)))
#endif
void USCI_B0_ISR(void)
{
    {
      switch(__even_in_range(UCB0IV,12))
      {
      case  0: break;                           // Vector  0: No interrupts
      case  2: break;                           // Vector  2: ALIFG
      case  4: break;                           // Vector  4: NACKIFG
      case  6: break;                           // Vector  6: STTIFG
      case  8: break;                           // Vector  8: STPIFG
      case 10:                                  // Vector 10: RXIFG
          if (RXByteCtr)
          {
              RXByteCtr--;
              RxBuf[RXByteCtr] = UCB0RXBUF;
              if(RXByteCtr==0)
              {
                  UCB0CTL1 |= UCTXSTP+UCTXNACK;    //必须在接受最后一个数据之前发送停止和NACK
              }
              UCB0CTL1 &=~UCTXNACK;
          }
          else
          {
              USCI_B_I2C_clearInterrupt(USCI_B0_BASE,USCI_B_I2C_RECEIVE_INTERRUPT);
          }
        break;
      case 12:
          if (TXByteCtr)                          // Check TX byte counter
          {
            TXByteCtr--;
            UCB0TXBUF = TxData[TXByteCtr];                // Load TX buffer
          }
          else
          {
            UCB0CTL1 |= UCTXSTP;                  // I2C stop condition
            UCB0IFG &= ~UCTXIFG;                  // Clear USCI_B0 TX int flag
          }
          break;                                // Vector 12: TXIFG
      default: break;
      }
    }
}


/****************************************************************Delay.h*********************************************************************************************************/
// 4M晶振
#ifndef __DELAY_H_
#define __DELAY_H_

#define CPU_F ((double)1000000)
#define Delay_us(x) __delay_cycles((long)(24*CPU_F*(double)x/1000000.0))
#define Delay_ms(x) __delay_cycles((long)(24*CPU_F*(double)x/1000.0))

#endif /* DELAY_H_ */

360截图20181021191024057.jpg (37.7 KB, 下载次数: 0)

360截图20181021191024057.jpg
 
点赞 关注

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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