[资料分享] MSP430F5529硬件IIC驱动IIC接口的OLED源码

fish001   2018-9-21 17:39 楼主
  • //******************************************************************************
  • //   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
  • #include
  • #include
  • #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;
  •           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],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;
  •   }
  • }


回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复