|
- //******************************************************************************
- // MSP430F552x Demo - USCI_B0, I2C Master multiple byte TX/RX
- //
- // Description: I2C master communicates to I2C slave sending and receiving
- // 3 different messages of different length. I2C master will enter LPM0 mode
- // while waiting for the messages to be sent/receiving using I2C interrupt.
- // ACLK = NA, MCLK = SMCLK = DCO 16MHz.
- //
- // /|\ /|\
- // MSP430F5529 4.7k |
- // ----------------- | 4.7k
- // /|\ | P3.1|---+---|-- I2C Clock (UCB0SCL)
- // | | | |
- // ---|RST P3.0|-------+-- I2C Data (UCB0SDA)
- // | |
- // | |
- // | |
- // | |
- // | |
- // | |
- //
- // Nima Eskandari
- // Texas Instruments Inc.
- // April 2017
- // Built with CCS V7.0
- //******************************************************************************
- #include <msp430.h>
- #include <stdint.h>
- #include <stdbool.h>
- #include "oledfont.h"
- //******************************************************************************
- // Example Commands ************************************************************
- //******************************************************************************
- #define X_WIDTH 128
- #define Y_WIDTH 64
- #define OLED_CMD 0 //写命令
- #define OLED_DATA 1 //写数据
- #define SLAVE_ADDR 0x3C
- /* CMD_TYPE_X_SLAVE are example commands the master sends to the slave.
- * The slave will send example SlaveTypeX buffers in response.
- *
- * CMD_TYPE_X_MASTER are example commands the master sends to the slave.
- * The slave will initialize itself to receive MasterTypeX example buffers.
- * */
- #define CMD_TYPE_0_SLAVE 0
- #define CMD_TYPE_1_SLAVE 1
- #define CMD_TYPE_2_SLAVE 2
- #define CMD_TYPE_0_MASTER 3
- #define CMD_TYPE_1_MASTER 4
- #define CMD_TYPE_2_MASTER 5
- #define TYPE_0_LENGTH 1
- #define TYPE_1_LENGTH 2
- #define TYPE_2_LENGTH 6
- #define MAX_BUFFER_SIZE 20
- /* MasterTypeX are example buffers initialized in the master, they will be
- * sent by the master to the slave.
- * SlaveTypeX are example buffers initialized in the slave, they will be
- * sent by the slave to the master.
- * */
- uint8_t MasterType2 [TYPE_2_LENGTH] = {'F', '4', '1', '9', '2', 'B'};
- uint8_t MasterType1 [28] = {0xae,0x00,0x10,0x40,0x81,0xcf,0xa1,0xc8,0xa6,0xa8,0x3f,0xd3,0x00,0xd5,0x80,0xd9,0xf1,0xda,0x12,0xdb,0x40,0x20,0x02,0x8d,0x14,0xa4,0xa6,0xaf};
- uint8_t MasterType0 [1] = {0};
- uint8_t SlaveType2 [TYPE_2_LENGTH] = {0};
- uint8_t SlaveType1 [TYPE_1_LENGTH] = {0};
- uint8_t SlaveType0 [TYPE_0_LENGTH] = {0};
- void delay(unsigned int z)
- {
- unsigned int x,y;
- for(x=z;x>0;x--)
- for(y=5000;y>0;y--);
- }
- //******************************************************************************
- // General I2C State Machine ***************************************************
- //******************************************************************************
- typedef enum I2C_ModeEnum{
- IDLE_MODE,
- NACK_MODE,
- TX_REG_ADDRESS_MODE,
- RX_REG_ADDRESS_MODE,
- TX_DATA_MODE,
- RX_DATA_MODE,
- SWITCH_TO_RX_MODE,
- SWITHC_TO_TX_MODE,
- TIMEOUT_MODE
- } I2C_Mode;
- /* Used to track the state of the software state machine*/
- I2C_Mode MasterMode = IDLE_MODE;
- /* The Register Address/Command to use*/
- uint8_t TransmitRegAddr = 0;
- /* ReceiveBuffer: Buffer used to receive data in the ISR
- * RXByteCtr: Number of bytes left to receive
- * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
- * TransmitBuffer: Buffer used to transmit data in the ISR
- * TXByteCtr: Number of bytes left to transfer
- * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
- * */
- uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
- uint8_t RXByteCtr = 0;
- uint8_t ReceiveIndex = 0;
- uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
- uint8_t TXByteCtr = 0;
- uint8_t TransmitIndex = 0;
- /* I2C Write and Read Functions */
- /* For slave device with dev_addr, writes the data specified in *reg_data
- *
- * dev_addr: The slave device address.
- * Example: SLAVE_ADDR
- * reg_addr: The register or command to send to the slave.
- * Example: CMD_TYPE_0_MASTER
- * *reg_data: The buffer to write
- * Example: MasterType0
- * count: The length of *reg_data
- * Example: TYPE_0_LENGTH
- * */
- I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);
- /* For slave device with dev_addr, read the data specified in slaves reg_addr.
- * The received data is available in ReceiveBuffer
- *
- * dev_addr: The slave device address.
- * Example: SLAVE_ADDR
- * reg_addr: The register or command to send to the slave.
- * Example: CMD_TYPE_0_SLAVE
- * count: The length of data to read
- * Example: TYPE_0_LENGTH
- * */
- I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count);
- void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);
- I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
- {
- /* Initialize state machine */
- MasterMode = TX_REG_ADDRESS_MODE;
- TransmitRegAddr = reg_addr;
- RXByteCtr = count;
- TXByteCtr = 0;
- ReceiveIndex = 0;
- TransmitIndex = 0;
- /* Initialize slave address and interrupts */
- UCB0I2CSA = dev_addr;
- UCB0IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
- UCB0IE &= ~UCRXIE; // Disable RX interrupt
- UCB0IE |= UCTXIE; // Enable TX interrupt
- UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
- __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
- return MasterMode;
- }
- I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
- {
- /* Initialize state machine */
- MasterMode = TX_REG_ADDRESS_MODE;
- TransmitRegAddr = reg_addr;
- //Copy register data to TransmitBuffer
- CopyArray(reg_data, TransmitBuffer, count);
- TXByteCtr = count;
- RXByteCtr = 0;
- ReceiveIndex = 0;
- TransmitIndex = 0;
- /* Initialize slave address and interrupts */
- UCB0I2CSA = dev_addr;
- UCB0IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
- UCB0IE &= ~UCRXIE; // Disable RX interrupt
- UCB0IE |= UCTXIE; // Enable TX interrupt
- UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
- __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
- return MasterMode;
- }
- void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
- {
- uint8_t copyIndex = 0;
- for (copyIndex = 0; copyIndex < count; copyIndex++)
- {
- dest[copyIndex] = source[copyIndex];
- }
- }
- //******************************************************************************
- // Device Initialization *******************************************************
- //******************************************************************************
- void initClockTo16MHz()
- {
- UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO
- UCSCTL4 |= SELA_2; // Set ACLK = REFO
- __bis_SR_register(SCG0); // Disable the FLL control loop
- UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
- UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation
- UCSCTL2 = FLLD_0 + 487; // Set DCO Multiplier for 16MHz
- // (N + 1) * FLLRef = Fdco
- // (487 + 1) * 32768 = 16MHz
- // Set FLL Div = fDCOCLK
- __bic_SR_register(SCG0); // Enable the FLL control loop
- // Worst-case settling time for the DCO when the DCO range bits have been
- // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
- // UG for optimization.
- // 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
- __delay_cycles(500000);//
- // Loop until XT1,XT2 & DCO fault flag is cleared
- do
- {
- UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
- SFRIFG1 &= ~OFIFG; // Clear fault flags
- }while (SFRIFG1&OFIFG); // Test oscillator fault flag
- }
- void initGPIO()
- {
- //I2C Pins
- P3SEL |= BIT0 + BIT1; // P3.0,1 option select
- }
- void initI2C()
- {
- UCB0CTL1 |= UCSWRST; // Enable SW reset(复位使能)
- UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // Master, I2C,synchronous mode(同步模式)
- UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
- UCB0BR0 = 160; // fSCL = SMCLK/160 = ~100kHz
- UCB0BR1 = 0;
- UCB0I2CSA = SLAVE_ADDR; // Slave Address is 048h
- UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
- UCB0IE |= UCNACKIE; //使能中断
- }
- void OLED_WrCmd(unsigned char IIC_Command)
- {
- MasterType0[0]=IIC_Command;
- I2C_Master_WriteReg(SLAVE_ADDR, 0x00,MasterType0, 1);
- }
- void OLED_WrDat(unsigned char IIC_Data)
- {
- MasterType0[0]=IIC_Data;
- I2C_Master_WriteReg(SLAVE_ADDR, 0x40,MasterType0, 1);
- }
- //******************************************************************************
- // Main ************************************************************************
- // Send and receive three messages containing the example commands *************
- //******************************************************************************
- void OLED_Fill(unsigned char bmp_dat)
- {
- unsigned char y,x;
- for(y=0;y<8;y++)
- {
- OLED_WrCmd(0xb0+y);
- OLED_WrCmd(0x01);
- OLED_WrCmd(0x10);
- for(x=0;x<128;x++)
- OLED_WrDat(bmp_dat);
- }
- }
- void OLED_Set_Pos(unsigned char x, unsigned char y)
- {
- OLED_WrCmd(0xb0+y);
- OLED_WrCmd(((x&0xf0)>>4)|0x10);
- OLED_WrCmd((x&0x0f)|0x01);
- }
- void OLED_Init(void)
- {
- unsigned char i=0;
- for(;i<28;i++)
- {
- MasterType0[0]=MasterType1[i];
- I2C_Master_WriteReg(SLAVE_ADDR, 0x00,MasterType0, 1);
- }
- OLED_Fill(0x00); //初始清屏
- OLED_Set_Pos(0,0);
- }
- void OLED_WR_Byte(unsigned dat,unsigned cmd)
- {
- if(cmd)
- {
- OLED_WrDat(dat);
-
- }
- else {
- OLED_WrCmd(dat);
-
- }
- }
- void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr,unsigned char Char_Size)
- {
- unsigned char c=0,i=0;
- c=chr-' ';//得到偏移后的值
- if(x>128-1){x=0;y=y+2;}
- if(Char_Size ==16)
- {
- OLED_Set_Pos(x,y);
- for(i=0;i<8;i++)
- OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
- OLED_Set_Pos(x,y+1);
- for(i=0;i<8;i++)
- OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
- }
- else {
- OLED_Set_Pos(x,y);
- for(i=0;i<6;i++)
- OLED_WR_Byte(F6x8[c][i],OLED_DATA);
-
- }
- }
- void OLED_U32toU16(unsigned char x,unsigned char y ,unsigned int n,unsigned char k)
- {
- switch(n)
- {
- case 0 :OLED_ShowChar(x,y,'0',k);break;
- case 1 :OLED_ShowChar(x,y,'1',k);break;
- case 2 :OLED_ShowChar(x,y,'2',k);break;
- case 3 :OLED_ShowChar(x,y,'3',k);break;
- case 4 :OLED_ShowChar(x,y,'4',k);break;
- case 5 :OLED_ShowChar(x,y,'5',k);break;
- case 6 :OLED_ShowChar(x,y,'6',k);break;
- case 7 :OLED_ShowChar(x,y,'7',k);break;
- case 8 :OLED_ShowChar(x,y,'8',k);break;
- case 9 :OLED_ShowChar(x,y,'9',k);break;
- }
- }
- void OLED_Show_Number(unsigned char x,unsigned char y ,unsigned int a,unsigned char n)
- {
- unsigned int b,c,d,e,f,g;
- b=a/100000;
- c=a%100000/10000;
- d=a%10000/1000;
- e=a%1000/100;
- f=a%100/10;
- g=a%10;
- if(b!=0)
- {
- OLED_U32toU16(x,y,b,n);
- OLED_U32toU16(x+n/2,y,c,n);
- OLED_U32toU16(x+n,y,d,n);
- OLED_U32toU16(x+(n/2)*3,y,e,n);
- OLED_U32toU16(x+2*n,y,f,n);
- OLED_U32toU16(x+(n/2)*5,y,g,n);
- }else if(b==0&&c!=0)
- {
- OLED_U32toU16(x,y,c,n);
- OLED_U32toU16(x+n/2,y,d,n);
- OLED_U32toU16(x+n,y,e,n);
- OLED_U32toU16(x+(n/2)*3,y,f,n);
- OLED_U32toU16(x+2*n,y,g,n);
- }else if(b==0&&c==0&&d!=0)
- {
- OLED_U32toU16(x,y,d,n);
- OLED_U32toU16(x+n/2,y,e,n);
- OLED_U32toU16(x+n,y,f,n);
- OLED_U32toU16(x+(n/2)*3,y,g,n);
- }else if(b==0&&c==0&&d==0&&e!=0)
- {
- OLED_U32toU16(x,y,e,n);
- OLED_U32toU16(x+n/2,y,f,n);
- OLED_U32toU16(x+n,y,g,n);
- }else if(b==0&&c==0&&d==0&&e==0&&f!=0)
- {
- OLED_U32toU16(x,y,f,n);
- OLED_U32toU16(x+n/2,y,g,n);
- }else
- {
- OLED_U32toU16(x,y,g,n);
- }
- }
- int main(void) {
- WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
- initClockTo16MHz(); //配置系统时钟为16Mhz
- initGPIO();
- initI2C();
- delay(500);
- OLED_Init();
- OLED_Show_Number(0,0,500,16);
- __bis_SR_register(LPM0_bits + GIE);
- }
- //******************************************************************************
- // I2C Interrupt ***************************************************************
- //******************************************************************************
- #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
- #pragma vector=USCI_B0_VECTOR
- __interrupt void USCI_B0_ISR(void)
- #elif defined(__GNUC__)
- void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
- #else
- #error Compiler not supported!
- #endif
- {
- //Must read from UCB0RXBUF
- uint8_t rx_val = 0;
- switch(__even_in_range(UCB0IV,0xC))
- {
- case USCI_NONE:break; // Vector 0 - no interrupt
- case USCI_I2C_UCALIFG:break; // Interrupt Vector: I2C Mode: UCALIFG
- case USCI_I2C_UCNACKIFG:break; // Interrupt Vector: I2C Mode: UCNACKIFG
- case USCI_I2C_UCSTTIFG:break; // Interrupt Vector: I2C Mode: UCSTTIFG
- case USCI_I2C_UCSTPIFG:break; // Interrupt Vector: I2C Mode: UCSTPIFG
- case USCI_I2C_UCRXIFG:
- rx_val = UCB0RXBUF;
- if (RXByteCtr)
- {
- ReceiveBuffer[ReceiveIndex++] = rx_val;
- RXByteCtr--;
- }
- if (RXByteCtr == 1)
- {
- UCB0CTL1 |= UCTXSTP;
- }
- else if (RXByteCtr == 0)
- {
- UCB0IE &= ~UCRXIE;
- MasterMode = IDLE_MODE;
- __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
- }
- break; // Interrupt Vector: I2C Mode: UCRXIFG
- case USCI_I2C_UCTXIFG:
- switch (MasterMode)
- {
- case TX_REG_ADDRESS_MODE:
- UCB0TXBUF = TransmitRegAddr;
- if (RXByteCtr)
- MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
- else
- MasterMode = TX_DATA_MODE; // Continue to transmission with the data in Transmit Buffer
- break;
- case SWITCH_TO_RX_MODE:
- UCB0IE |= UCRXIE; // Enable RX interrupt
- UCB0IE &= ~UCTXIE; // Disable TX interrupt
- UCB0CTL1 &= ~UCTR; // Switch to receiver
- MasterMode = RX_DATA_MODE; // State state is to receive data
- UCB0CTL1 |= UCTXSTT; // Send repeated start
- if (RXByteCtr == 1)
- {
- //Must send stop since this is the N-1 byte
- while((UCB0CTL1 & UCTXSTT));
- UCB0CTL1 |= UCTXSTP; // Send stop condition
- }
- break;
- case TX_DATA_MODE:
- if (TXByteCtr)
- {
- UCB0TXBUF = TransmitBuffer[TransmitIndex++];
- TXByteCtr--;
- }
- else
- {
- //Done with transmission
- UCB0CTL1 |= UCTXSTP; // Send stop condition
- MasterMode = IDLE_MODE;
- UCB0IE &= ~UCTXIE; // disable TX interrupt
- __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
- }
- break;
- default:
- __no_operation();
- break;
- }
- break; // Interrupt Vector: I2C Mode: UCTXIFG
- default: break;
- }
- }
复制代码
|
评分
-
查看全部评分
|