This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR4133:MSP430FR4133 I2C 帮助

Guru**** 1138100 points
Other Parts Discussed in Thread: MSP430FR4133
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1329533/msp430fr4133-msp430fr4133-i2c-help

器件型号:MSP430FR4133

大家好、我希望有人可以帮助我配置 MSP430Fr4133以便与 SSD1306 I2C 显示屏配合使用?

// I2C.c

#include "i2c.h"
#include <msp430fr4133.h>
#include <stdint.h>

#define SDA BIT2                                                        // i2c sda P5.2
#define SCL BIT3                                                        // i2c scl P5.3

unsigned char* PTxData;                                                       // Pointer to TX data
unsigned char TxByteCtr;                                                      // number of bytes to TX


void i2c_init(void) {
    P5SEL0   |= SCL + SDA;                                              // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST;                                                // Enable SW reset
    UCB0CTLW0  = UCMST + UCMODE_3 + UCSYNC;                              // I2C Master, synchronous mode
    UCB0CTL1  = UCSSEL_2 + UCSWRST;                                     // Use SMCLK, keep SW reset
    UCB0BRW   = 10;                                                     // fSCL = SMCLK/10 = ~100kHz with SMCLK 1MHz
    UCB0BRW   = 0;
    UCB0CTL1 &= ~UCSWRST;                                               // Clear SW reset, resume operation
    UCB0IE |= UCTXIE0;                                                  // Enable TX interrupt

} // end i2c_init

void i2c_write(unsigned char slave_address, unsigned char *DataBuffer, unsigned char ByteCtr) {
    UCB0I2CSA = slave_address;

    PTxData = DataBuffer;
    TxByteCtr = ByteCtr;

    while (UCB0CTL1 & UCTXSTP);                                         // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT;                                         // I2C TX, start condition
    while (UCB0CTL1 & UCTXSTP);                                         // Ensure stop condition got sent
    __bis_SR_register(CPUOFF + GIE);                                    // Enter LPM0 w/ interrupts
                                                                        // Remain in LPM0 until all data is TX'd
}


#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void){
switch(__even_in_range(UCB0IV,0x1E))
{
        case USCI_NONE:          break;               // Vector 0: No interrupts break;
        case USCI_I2C_UCALIFG:   break;
        case USCI_I2C_UCNACKIFG: break;
        case USCI_I2C_UCSTTIFG:  break;               // Vector 6: STTIFG break;
        case USCI_I2C_UCSTPIFG:  break;               // Vector 8: STPIFG break;
        case USCI_I2C_UCRXIFG3:  break;               // Vector 10: RXIFG3 break;
        case USCI_I2C_UCTXIFG3:  break;               // Vector 14: TXIFG3 break;
        case USCI_I2C_UCRXIFG2:  break;               // Vector 16: RXIFG2 break;
        case USCI_I2C_UCTXIFG2:  break;               // Vector 18: TXIFG2 break;
        case USCI_I2C_UCRXIFG1:  break;               // Vector 20: RXIFG1 break;
        case USCI_I2C_UCTXIFG1:  break;               // Vector 22: TXIFG1 break;
        case USCI_I2C_UCRXIFG0:  break;               // Vector 24: RXIFG0 break;
        case USCI_I2C_UCTXIFG0:
            if (TxByteCtr)
            {                                         // Check TX byte counter
                    UCB0TXBUF = *PTxData++;           // Load TX buffer
                    TxByteCtr--;                      // Decrement TX byte counter
            }
            else
            {
                    UCB0CTL1 |= UCTXSTP;              // I2C stop condition
                    UCB0IE &= ~UCTXIE0;                // Clear USCI_B0 TX int flag
                    __bic_SR_register_on_exit(CPUOFF);// Exit LPM0
            }
          break;                                      // Vector 26: TXIFG0 break;
        case USCI_I2C_UCBCNTIFG: break;               // Vector 28: BCNTIFG
        case USCI_I2C_UCCLTOIFG: break;               // Vector 30: clock low timeout
        case USCI_I2C_UCBIT9IFG: break;               // Vector 32: 9th bit
        default: break;
  }
}

//I2C.h

#ifndef I2C_H_
#define I2C_H_

#include <msp430fr4133.h>

/* ====================================================================
 * I2C Prototype Definitions
 * ==================================================================== */
void i2c_init(void);
void i2c_write(unsigned char, unsigned char *, unsigned char);

#endif /* I2C_H_ */


/*
 * ssd1306.h
 */

#ifndef SSD1306_H_
#define SSD1306_H_

#include <msp430fr4133.h>
#include <stdint.h>
#include <string.h>
#include "i2c.h"

/* ====================================================================
 * Horizontal Centering Number Array
 * ==================================================================== */
#define HCENTERUL_OFF   0
#define HCENTERUL_ON    1

/* ====================================================================
 * SSD1306 OLED Settings and Command Definitions
 * ==================================================================== */

#define SSD1306_I2C_ADDRESS             0x3C

#define SSD1306_LCDWIDTH                128
#define SSD1306_LCDHEIGHT               64
#define SSD1306_128_64

#define SSD1306_SETCONTRAST             0x81
#define SSD1306_DISPLAYALLON_RESUME     0xA4
#define SSD1306_DISPLAYALLON            0xA5
#define SSD1306_NORMALDISPLAY           0xA6
#define SSD1306_INVERTDISPLAY           0xA7
#define SSD1306_DISPLAYOFF              0xAE
#define SSD1306_DISPLAYON               0xAF

#define SSD1306_SETDISPLAYOFFSET        0xD3
#define SSD1306_SETCOMPINS              0xDA

#define SSD1306_SETVCOMDETECT           0xDB

#define SSD1306_SETDISPLAYCLOCKDIV      0xD5
#define SSD1306_SETPRECHARGE            0xD9

#define SSD1306_SETMULTIPLEX            0xA8

#define SSD1306_SETLOWCOLUMN            0x00
#define SSD1306_SETHIGHCOLUMN           0x10

#define SSD1306_SETSTARTLINE            0x40

#define SSD1306_MEMORYMODE              0x20
#define SSD1306_COLUMNADDR              0x21
#define SSD1306_PAGEADDR                0x22

#define SSD1306_COMSCANINC              0xC0
#define SSD1306_COMSCANDEC              0xC8

#define SSD1306_SEGREMAP                0xA0

#define SSD1306_CHARGEPUMP              0x8D

#define SSD1306_EXTERNALVCC             0x1
#define SSD1306_SWITCHCAPVCC            0x2

// currently no scroll functionality, left for possible future use
#define SSD1306_ACTIVATE_SCROLL                         0x2F
#define SSD1306_DEACTIVATE_SCROLL                       0x2E
#define SSD1306_SET_VERTICAL_SCROLL_AREA                0xA3
#define SSD1306_RIGHT_HORIZONTAL_SCROLL                 0x26
#define SSD1306_LEFT_HORIZONTAL_SCROLL                  0x27
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL    0x29
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL     0x2A


/* ====================================================================
 * SSD1306 OLED Prototype Definitions
 * ==================================================================== */
void ssd1306_init(void);
void ssd1306_command(unsigned char);
void ssd1306_clearDisplay(void);
void ssd1306_setPosition(uint8_t, uint8_t);
void ssd1306_printText(uint8_t, uint8_t, char *);
void ssd1306_printTextBlock(uint8_t, uint8_t, char *);
void ssd1306_printUI32(uint8_t, uint8_t, uint32_t, uint8_t);

uint8_t digits(uint32_t);
void ultoa(uint32_t, char *);
void reverse(char *);

#endif /* SSD1306_H_ */

/*
 * ssd1306.c
 */

#include "ssd1306.h"
#include <msp430fr4133.h>
#include <stdint.h>
#include "font_5x7.h"
#include "i2c.h"

/* ====================================================================
 * Horizontal Centering Number Array
 * ==================================================================== */
   
unsigned char buffer[17];                                                     // buffer for data transmission to screen

const unsigned char HcenterUL[] = {                                           // Horizontally center number with separators on screen
                               0,                                       // 0 digits, not used but included to size array correctly
                               61,                                      // 1 digit
                               58,                                      // 2 digits
                               55,                                      // 3 digits
                               49,                                      // 4 digits and 1 separator
                               46,                                      // 5 digits and 1 separator
                               43,                                      // 6 digits and 1 separator
                               37,                                      // 7 digits and 2 separators
                               34,                                      // 8 digits and 2 separators
                               31,                                      // 9 digits and 2 separators
                               25                                       // 10 digits and 3 separators
};

void ssd1306_init(void) {
    // SSD1306 init sequence
    ssd1306_command(SSD1306_DISPLAYOFF);                                // 0xAE
    ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV);                        // 0xD5
    ssd1306_command(0x80);                                              // the suggested ratio 0x80

    ssd1306_command(SSD1306_SETMULTIPLEX);                              // 0xA8
    ssd1306_command(SSD1306_LCDHEIGHT - 1);

    ssd1306_command(SSD1306_SETDISPLAYOFFSET);                          // 0xD3
    ssd1306_command(0x0);                                               // no offset
    ssd1306_command(SSD1306_SETSTARTLINE | 0x0);                        // line #0
    ssd1306_command(SSD1306_CHARGEPUMP);                                // 0x8D
    ssd1306_command(0x14);                                              // generate high voltage from 3.3v line internally
    ssd1306_command(SSD1306_MEMORYMODE);                                // 0x20
    ssd1306_command(0x00);                                              // 0x0 act like ks0108
    ssd1306_command(SSD1306_SEGREMAP | 0x1);
    ssd1306_command(SSD1306_COMSCANDEC);

    ssd1306_command(SSD1306_SETCOMPINS);                                // 0xDA
    ssd1306_command(0x12);
    ssd1306_command(SSD1306_SETCONTRAST);                               // 0x81
    ssd1306_command(0xCF);

    ssd1306_command(SSD1306_SETPRECHARGE);                              // 0xd9
    ssd1306_command(0xF1);
    ssd1306_command(SSD1306_SETVCOMDETECT);                             // 0xDB
    ssd1306_command(0x40);
    ssd1306_command(SSD1306_DISPLAYALLON_RESUME);                       // 0xA4
    ssd1306_command(SSD1306_NORMALDISPLAY);                             // 0xA6

    ssd1306_command(SSD1306_DEACTIVATE_SCROLL);

    ssd1306_command(SSD1306_DISPLAYON);                                 //--turn on oled panel
} // end ssd1306_init

void ssd1306_command(unsigned char command) {
    buffer[0] = 0x80;
    buffer[1] = command;

    i2c_write(SSD1306_I2C_ADDRESS, buffer, 2);
} // end ssd1306_command

void ssd1306_clearDisplay(void) {

    ssd1306_setPosition(0, 0);
    uint8_t i;
    for (i = 64; i > 0; i--) {                                          // count down for loops when possible for ULP
        uint8_t x;
        for(x = 16; x > 0; x--) {
            if (x == 1) {
                buffer[x-1] = 0x40;
            } else {
                buffer[x-1] = 0x0;
            }
        }

        i2c_write(SSD1306_I2C_ADDRESS, buffer, 17);
    }
} // end ssd1306_clearDisplay

void ssd1306_setPosition(uint8_t column, uint8_t page) {
    if (column > 128) {
        column = 0;                                                     // constrain column to upper limit
    }

    if (page > 8) {
        page = 0;                                                       // constrain page to upper limit
    }

    ssd1306_command(SSD1306_COLUMNADDR);
    ssd1306_command(column);                                            // Column start address (0 = reset)
    ssd1306_command(SSD1306_LCDWIDTH-1);                                // Column end address (127 = reset)

    ssd1306_command(SSD1306_PAGEADDR);
    ssd1306_command(page);                                              // Page start address (0 = reset)
    ssd1306_command(7);                                                 // Page end address
} // end ssd1306_setPosition

void ssd1306_printText(uint8_t x, uint8_t y, char *ptString) {
    ssd1306_setPosition(x, y);

    while (*ptString != '\0') {
        buffer[0] = 0x40;

        if ((x + 5) >= 127) {                                           // char will run off screen
            x = 0;                                                      // set column to 0
            y++;                                                        // jump to next page
            ssd1306_setPosition(x, y);                                  // send position change to oled
        }

        uint8_t i;
        for(i = 0; i< 5; i++) {
            buffer[i+1] = font_5x7[*ptString - ' '][i];
        }

        buffer[6] = 0x0;

        i2c_write(SSD1306_I2C_ADDRESS, buffer, 7);
        ptString++;
        x+=6;
    }
} // end ssd1306_printText

void ssd1306_printTextBlock(uint8_t x, uint8_t y, char *ptString) {
    char word[12];
    uint8_t i;
    uint8_t endX = x;
    while (*ptString != '\0'){
        i = 0;
        while ((*ptString != ' ') && (*ptString != '\0')) {
            word[i] = *ptString;
            ptString++;
            i++;
            endX += 6;
        }

        word[i++] = '\0';

        if (endX >= 127) {
            x = 0;
            y++;
            ssd1306_printText(x, y, word);
            endX = (i * 6);
            x = endX;
        } else {
            ssd1306_printText(x, y, word);
            endX += 6;
            x = endX;
        }
        ptString++;
    }

}


void ssd1306_printUI32( uint8_t x, uint8_t y, uint32_t val, uint8_t Hcenter ) {
    char text[14];

    ultoa(val, text);
    if (Hcenter) {
        ssd1306_printText(HcenterUL[digits(val)], y, text);
    } else {
        ssd1306_printText(x, y, text);
    }
} // end ssd1306_printUI32

uint8_t digits(uint32_t n) {
    if (n < 10) {
        return 1;
    } else if (n < 100) {
        return 2;
    } else if (n < 1000) {
        return 3;
    } else if (n < 10000) {
        return 4;
    } else if (n < 100000) {
        return 5;
    } else if (n < 1000000) {
        return 6;
    } else if (n < 10000000) {
        return 7;
    } else if (n < 100000000) {
        return 8;
    } else if (n < 1000000000) {
        return 9;
    } else {
        return 10;
    }
} // end digits

void ultoa(uint32_t val, char *string) {
    uint8_t i = 0;
    uint8_t j = 0;
                                                                        // use do loop to convert val to string
    do {
        if (j==3) {                                                     // we have reached a separator position
            string[i++] = ',';                                          // add a separator to the number string
            j=0;                                                        // reset separator indexer thingy
        }
            string[i++] = val%10 + '0';                                 // add the ith digit to the number string
            j++;                                                        // increment counter to keep track of separator placement
    } while ((val/=10) > 0);

    string[i++] = '\0';                                                 // add termination to string
    reverse(string);                                                    // string was built in reverse, fix that
} // end ultoa

void reverse(char *s)
{
    uint8_t i, j;
    uint8_t c;

    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
} // end reverse

/*
 * font_5x7.h
 */

#ifndef FONT_5X7_H_
#define FONT_5X7_H_

const unsigned char font_5x7[96][5] = {{0x00, 0x00, 0x00, 0x00, 0x00},  // space
                                       {0x00, 0x00, 0x4F, 0x00, 0x00},  // !
                                       {0x00, 0x07, 0x00, 0x07, 0x00},  // "
                                       {0x14, 0x7F, 0x14, 0x7F, 0x14},  // #
                                       {0x24, 0x2A, 0x7F, 0x2A, 0x12},  // $
                                       {0x23, 0x13, 0x08, 0x64, 0x62},  // %
                                       {0x36, 0x49, 0x55, 0x22, 0x50},  // &
                                       {0x00, 0x05, 0x03, 0x00, 0x00},  // '
                                       {0x00, 0x1C, 0x22, 0x41, 0x00},  // (
                                       {0x00, 0x41, 0x22, 0x1C, 0x00},  // )
                                       {0x14, 0x08, 0x3E, 0x08, 0x14},  // *
                                       {0x08, 0x08, 0x3E, 0x08, 0x08},  // +
                                       {0x00, 0x50, 0x30, 0x00, 0x00},  // ,
                                       {0x08, 0x08, 0x08, 0x08, 0x08},  // -
                                       {0x00, 0x60, 0x60, 0x00, 0x00},  // .
                                       {0x20, 0x10, 0x08, 0x04, 0x02},  // /
                                       {0x3E, 0x51, 0x49, 0x45, 0x3E},  // 0
                                       {0x00, 0x42, 0x7F, 0x40, 0x00},  // 1
                                       {0x42, 0x61, 0x51, 0x49, 0x46},  // 2
                                       {0x21, 0x41, 0x45, 0x4B, 0x31},  // 3
                                       {0x18, 0x14, 0x12, 0x7F, 0x10},  // 4
                                       {0x27, 0x49, 0x49, 0x49, 0x31},  // 5
                                       {0x3C, 0x4A, 0x49, 0x49, 0x30},  // 6
                                       {0x01, 0x71, 0x09, 0x05, 0x03},  // 7
                                       {0x36, 0x49, 0x49, 0x49, 0x36},  // 8
                                       {0x06, 0x49, 0x49, 0x29, 0x1E},  // 9
                                       {0x00, 0x36, 0x36, 0x00, 0x00},  // :
                                       {0x00, 0x56, 0x36, 0x00, 0x00},  // ;
                                       {0x08, 0x14, 0x22, 0x41, 0x00},  // <
                                       {0x14, 0x14, 0x14, 0x14, 0x14},  // =
                                       {0x00, 0x41, 0x22, 0x14, 0x08},  // >
                                       {0x02, 0x01, 0x51, 0x09, 0x06},  // ?
                                       {0x32, 0x49, 0x79, 0x41, 0x3E},  // @
                                       {0x7E, 0x11, 0x11, 0x11, 0x7E},  // A
                                       {0x7F, 0x49, 0x49, 0x49, 0x36},  // B
                                       {0x3E, 0x41, 0x41, 0x41, 0x22},  // C
                                       {0x7F, 0x41, 0x41, 0x22, 0x1C},  // D
                                       {0x7F, 0x49, 0x49, 0x49, 0x41},  // E
                                       {0x7F, 0x09, 0x09, 0x09, 0x01},  // F
                                       {0x3E, 0x41, 0x49, 0x49, 0x7A},  // G
                                       {0x7F, 0x08, 0x08, 0x08, 0x7F},  // H
                                       {0x00, 0x41, 0x7F, 0x41, 0x00},  // I
                                       {0x20, 0x40, 0x41, 0x3F, 0x01},  // J
                                       {0x7F, 0x08, 0x14, 0x22, 0x41},  // K
                                       {0x7F, 0x40, 0x40, 0x40, 0x40},  // L
                                       {0x7F, 0x02, 0x0C, 0x02, 0x7F},  // M
                                       {0x7F, 0x04, 0x08, 0x10, 0x7F},  // N
                                       {0x3E, 0x41, 0x41, 0x41, 0x3E},  // O
                                       {0x7F, 0x09, 0x09, 0x09, 0x06},  // P
                                       {0x3E, 0x41, 0x51, 0x21, 0x5E},  // Q
                                       {0x7F, 0x09, 0x19, 0x29, 0x46},  // R
                                       {0x46, 0x49, 0x49, 0x49, 0x31},  // S
                                       {0x01, 0x01, 0x7F, 0x01, 0x01},  // T
                                       {0x3F, 0x40, 0x40, 0x40, 0x3F},  // U
                                       {0x1F, 0x20, 0x40, 0x20, 0x1F},  // V
                                       {0x3F, 0x40, 0x38, 0x40, 0x3F},  // W
                                       {0x63, 0x14, 0x08, 0x14, 0x63},  // X
                                       {0x07, 0x08, 0x70, 0x08, 0x07},  // Y
                                       {0x61, 0x51, 0x49, 0x45, 0x43},  // Z
                                       {0x7F, 0x41, 0x41, 0x00, 0x00},  // [
                                       {0x02, 0x04, 0x08, 0x10, 0x20},  // forward slash
                                       {0x00, 0x41, 0x41, 0x7F, 0x00},  // ]
                                       {0x04, 0x02, 0x01, 0x02, 0x04},  // ^
                                       {0x40, 0x40, 0x40, 0x40, 0x40},  // _
                                       {0x00, 0x01, 0x02, 0x04, 0x00},  // `
                                       {0x20, 0x54, 0x54, 0x54, 0x78},  // a
                                       {0x7F, 0x48, 0x44, 0x44, 0x38},  // b
                                       {0x38, 0x44, 0x44, 0x44, 0x20},  // c
                                       {0x38, 0x44, 0x44, 0x48, 0x7F},  // d
                                       {0x38, 0x54, 0x54, 0x54, 0x18},  // e
                                       {0x08, 0x7E, 0x09, 0x01, 0x02},  // f
                                       {0x0C, 0x52, 0x52, 0x52, 0x3E},  // g
                                       {0x7F, 0x08, 0x04, 0x04, 0x78},  // h
                                       {0x00, 0x44, 0x7D, 0x40, 0x00},  // i
                                       {0x20, 0x40, 0x44, 0x3D, 0x00},  // j
                                       {0x7F, 0x10, 0x28, 0x44, 0x00},  // k
                                       {0x00, 0x41, 0x7F, 0x40, 0x00},  // l
                                       {0x7C, 0x04, 0x18, 0x04, 0x78},  // m
                                       {0x7C, 0x08, 0x04, 0x04, 0x78},  // n
                                       {0x38, 0x44, 0x44, 0x44, 0x38},  // o
                                       {0x7C, 0x14, 0x14, 0x14, 0x08},  // p
                                       {0x08, 0x14, 0x14, 0x18, 0x7C},  // q
                                       {0x7C, 0x08, 0x04, 0x04, 0x08},  // r
                                       {0x48, 0x54, 0x54, 0x54, 0x20},  // s
                                       {0x04, 0x3F, 0x44, 0x40, 0x20},  // t
                                       {0x3C, 0x40, 0x40, 0x20, 0x7C},  // u
                                       {0x1C, 0x20, 0x40, 0x20, 0x1C},  // v
                                       {0x3C, 0x40, 0x30, 0x40, 0x3C},  // w
                                       {0x44, 0x28, 0x10, 0x28, 0x44},  // x
                                       {0x0C, 0x50, 0x50, 0x50, 0x3C},  // y
                                       {0x44, 0x64, 0x54, 0x4C, 0x44},  // z
};

#endif /* FONT_5X7_H_ */

#include <msp430fr4133.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "SSD1306.h"
#include "i2c.h"

#define ANUMBER     19052019
#define MAX_COUNT   4.2e9
#define LONG_DELAY  __delay_cycles(3000000)
#define SHORT_DELAY __delay_cycles(50000)

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;	                // stop watchdog timer

    i2c_init();                                 // initialize I2C to use with OLED
  
    ssd1306_init();                             // Initialize SSD1306 OLED
    ssd1306_clearDisplay();                     // Clear OLED display
    
    
    __enable_interrupt();
    PMM_unlockLPM5();

    while(1) {
        // =========================================
        // Display a Long Text Block
        // =========================================
        // There seems to be a bug in the ssd1306_printTextBlock code,
        //  long text blocks like below need 1 extra character in their array
        //  so the code does not read outside of the array. The below 91 character
        //  text block should only need a array of 92 but to fix the bug use an array of 93.
        //  !!!! MUST FIX BUG IN THE FUTURE !!!!
        char txtBlock[93] = "This is a long multiline text block. The code will automatically add extra lines as needed.";
        ssd1306_printTextBlock(0, 1, txtBlock);
        LONG_DELAY;                             // Avoid delay loops in real code, use timer
        ssd1306_clearDisplay();

        // =========================================
        // Print Single Lines of Text at each row
        // =========================================
        ssd1306_printText(0, 1, "Line 1");
        ssd1306_printText(0, 2, "Line 2");
        ssd1306_printText(0, 3, "Line 3");
        ssd1306_printText(0, 4, "Line 4");
        ssd1306_printText(0, 5, "Line 5");
        ssd1306_printText(0, 6, "Line 6");
        ssd1306_printText(0, 7, "Line 7");

        // Print these at a column other then zero
        ssd1306_printText(40, 1, "40");
        ssd1306_printText(50, 2, "50");
        ssd1306_printText(60, 3, "60");
        ssd1306_printText(70, 4, "70");
        ssd1306_printText(80, 5, "80");
        ssd1306_printText(90, 6, "90");
        ssd1306_printText(100, 7, "100");

        // Hold screen for some time before displaying the next sample
        LONG_DELAY;                              // Avoid delay loops in real code, use timer
        ssd1306_clearDisplay();

        // =========================================
        // Print Unsigned 32 bit number
        // =========================================
        ssd1306_printUI32(0, 1, ANUMBER, HCENTERUL_OFF);  // Print number on line 1
        ssd1306_printUI32(0, 2, ANUMBER, HCENTERUL_ON);   // Print number on line 2, horizontally centered

        // Print counting on line 6 horizontally centered
        uint32_t i = 1;
        uint32_t j;
        uint32_t val = 0;
        while (i<1e9) {
            for(j=0; j<10; j++) {
                val = i * j;
                ssd1306_printUI32(0, 6 , val, HCENTERUL_ON);
                SHORT_DELAY;
            }
            i *= 10;
        }

        for (j=0; j<5; j++) {
            val = i * j;
            ssd1306_printUI32(0, 6 , val, HCENTERUL_ON);
            SHORT_DELAY;
        }

        LONG_DELAY;
        ssd1306_clearDisplay();
    }
}

我附上了代码供参考。 我认为这个问题可能与 I2C 引脚/中断矢量的配置有关、因为这是我从原始库进行的更改、在 GitHub 上对代码进行了调整。 非常感谢您的任何帮助! 谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它在您运行时有什么作用?

    ----------------

    > PMM_unlockLPM5 ();

    将其上移、使其在调用 ssd1306 _init (或甚至在 i2c_init 之前)之前、因为它需要运行 GPIO。

    ----------------

    我还建议您检查 NACK (UCNACKIE/USCI_I2C_UCNACKIFG)、以防万一。   

    [编辑:更正了拼写错误。]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Bruce、感谢您的回复。 我已经纳入了你的建议,但仍然没有运气。 屏幕不显示任何内容。 从进行一些调试(在中断矢量处设置断点)、代码似乎从不 进入中断例程。 我已根据使用 I2C 的 MSP Academy 示例修改了寄存器、并获得以下代码。 不过、屏幕上仍然没有输出。 感谢您尝试解决此问题。

    #include "i2c.h"
    #include <msp430fr4133.h>
    #include <stdint.h>
    
    #define SDA BIT2                                                        // i2c sda P5.2
    #define SCL BIT3                                                        // i2c scl P5.3
    
    unsigned char *PTxData;                                                       // Pointer to TX data
    unsigned char TxByteCtr;                                                      // number of bytes to TX
    
    void i2c_init(void) {
        P5SEL0   |= SCL + SDA;                                              // Assign I2C pins to USCI_B0
        UCB0CTLW0 |= UCSWRST;                                                // Enable SW reset
        UCB0CTLW0  = UCMST + UCMODE_3 + UCSYNC;                              // I2C Master, synchronous mode
        UCB0CTLW0  = UCSSEL_2 + UCSWRST;                                     // Use SMCLK, keep SW reset
        UCB0BRW   = 10;                                                     // fSCL = SMCLK/10 = ~100kHz with SMCLK 1MHz
        UCB0BRW   = 0;
        UCB0CTLW0 &= ~UCSWRST;                                               // Clear SW reset, resume operation
        UCB0IE |= UCTXIE0 | UCNACKIE;                                                 // Enable TX interrupt
    
    } // end i2c_init
    
    void i2c_write(unsigned char slave_address, unsigned char *DataBuffer, unsigned char ByteCtr) {
        UCB0I2CSA = slave_address;
    
        PTxData = DataBuffer;
        TxByteCtr = ByteCtr;
    
        while (UCB0CTLW0 & UCTXSTP);                                         // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR + UCTXSTT;                                         // I2C TX, start condition
        while (UCB0CTLW0 & UCTXSTP);                                         // Ensure stop condition got sent                                                                        // Remain in LPM0 until all data is TX'd
    }
    
    
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void){
    switch(__even_in_range(UCB0IV,0x1E))
    {
            case USCI_NONE:          break;               // Vector 0: No interrupts break;
            case USCI_I2C_UCALIFG:   break;
            case USCI_I2C_UCNACKIFG:
                // do something
                break;
            case USCI_I2C_UCSTTIFG:  break;               // Vector 6: STTIFG break;
            case USCI_I2C_UCSTPIFG:  break;               // Vector 8: STPIFG break;
            case USCI_I2C_UCRXIFG3:  break;               // Vector 10: RXIFG3 break;
            case USCI_I2C_UCTXIFG3:  break;               // Vector 14: TXIFG3 break;
            case USCI_I2C_UCRXIFG2:  break;               // Vector 16: RXIFG2 break;
            case USCI_I2C_UCTXIFG2:  break;               // Vector 18: TXIFG2 break;
            case USCI_I2C_UCRXIFG1:  break;               // Vector 20: RXIFG1 break;
            case USCI_I2C_UCTXIFG1:  break;               // Vector 22: TXIFG1 break;
            case USCI_I2C_UCRXIFG0:  break;               // Vector 24: RXIFG0 break;
            case USCI_I2C_UCTXIFG0:
                if (TxByteCtr)
                {                                         // Check TX byte counter
                        UCB0TXBUF = *PTxData++;           // Load TX buffer
                        TxByteCtr--;                      // Decrement TX byte counter
                }
                else
                {
                        UCB0CTLW0 |= UCTXSTP;               // I2C stop condition
                        UCB0IFG &= ~UCTXIFG;
                }
              break;                                      // Vector 26: TXIFG0 break;
            case USCI_I2C_UCBCNTIFG: break;               // Vector 28: BCNTIFG
            case USCI_I2C_UCCLTOIFG: break;               // Vector 30: clock low timeout
            case USCI_I2C_UCBIT9IFG: break;               // Vector 32: 9th bit
            default: break;
      }
    }
    
    
    // main.c, prior to while loop
    
    WDTCTL = WDTPW | WDTHOLD;	                // stop watchdog timer
    PMM_unlockLPM5();
    __enable_interrupt();
    i2c_init();                                 // initialize I2C to use with OLED
    ssd1306_init();                             // Initialize SSD1306 OLED
    ssd1306_clearDisplay();                     // Clear OLED display

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这有问题:

        UCB0CTLW0 |= UCSWRST;                                                // Enable SW reset
        UCB0CTLW0  = UCMST + UCMODE_3 + UCSYNC;                              // I2C Master, synchronous mode
        UCB0CTLW0  = UCSSEL_2 + UCSWRST; 

    至少可以将它从混合字和字节访问的第一个版本更改为更糟糕的版本。

    行2清零 UCSWRST、行3清零行2中所做的设置。

    它应该与以下代码类似:

        UCB0CTLW0 = UCSWRST;                                                // Enable SW reset
        UCB0CTLW0  |= UCMST | UCMODE_3 | UCSYNC | UCSSEL_2;                 // I2C Master, synchronous mode
      

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢、David。 出于某些原因、只有当我在宏之间使用"+"符号而不是"|"符号时、代码才会进入 ISR。 此代码现在触发 ISR:

    void i2c_init (void){

      P5SEL0 |= SCL;//将 I2C 引脚分配至 USCI_B0

      P5SEL0 |= SDA;

      UCB0CTLW0 |= UCSWRST;//启用软件复位

      UCB0CTLW0 |= UCMST + UCMODE_3 + UCSYNC;// I2C 主器件、同步模式

      UCB0CTLW0 |= UCSSEL_2 + UCSWRST;//使用 SMCLK,保持软件复位

      UCB0BRW = 10;// fSCL = SMCLK/10 =~100kHz 及 SMCLK 1MHz

      UCB0BRW = 0;

      UCB0CTLW0 &=~μ A UCSWRST;//清除软件复位、恢复操作

      UCB0IE |= UCTXIE0;//启用 TX 中断

    }//结束 i2c_init

    但使用 UCB0CTLW0 |= UCSSEL_2 | UCSWRST 将不起作用。 屏幕上仍然没有输出、但这是一个进步。 您能否说明什么时候使用字节/字访问更好? 我曾查看过相关的用户指南、但并未真正按照其中的说明操作。 感谢您的帮助  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    字节访问是从真正旧的 MSP430器件进行的保留、而旧的 MSP430器件也是如此。 TI 为那些从那里开始并倾向于该方式的符号提供了帮助。 我不喜欢它、因为当我看到 UCB0CTL1时、我认为高字节实际上是低字节。 太令人困惑了。 它是一个字寄存器使用字访问。

    设置比特率的代码使用字访问、但在写入时假定有两个字节访问。 你不仅得到太快的比特率,但你违反了 brclk/4限制。

    由于这些寄存器中的所有字段不重叠、因此 按位或与加法之间的结果不应有差异。 我更喜欢使用位元或、因为我真的不想在位之间进行进位。 即使是在偶然情况下。

    另一个问题是、寄存器在复位后并不总是为零。 (请参阅文档。) 例如、UCCSEL 为3。 这一次不是问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢详细的答复,大卫。 我将在船上提供许多有用的信息、试着让它正常工作。 加油打气  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您已删除 i2c_write 最后一行中的"_ bis_SR_register (CPUOFF + GIE);"。 这是维护调度的内容。 现在一样、代码将循环运行、并在前一个操作完成前尝试开始一个新操作。 我建议您将这条线放回。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Bruce 的检查和建议。

    尊敬的 Ross:

    如果仍存在问题、请分享您正在使用的新代码。

    同时、我还有进一步的调试建议-请检查 IIC 总线中的信号波形、当 没有数据或 时钟/数据不正确时。

    B.R.

    萨尔

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Bruce 和 Sal 的支持。 我认为可能需要将 UCTXIE0更改为 UCTXIE2、因为原始库(为不同的 MSP 器件编写、使用的是 IE2 |= UCB0TXIE 行)。 显然、我的器件上没有 IE2寄存器、因此这可能是问题的根源。 我明天会用示波器尝试你的建议、Sal。 再次感谢你们  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    UCTXIFG2 (UCTXIE2)只在使用多个地址的从器件上触发(特别是 UCB0I2COA2)、但情况并非如此。 UCTXIE 与 UCTXIE0相同。

    [编辑:次要澄清。]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 Bruce。 节省了几个小时!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大卫已经指出了这一点:

    >  UCB0BRW = 10;// fSCL = SMCLK/10 =~100kHz 及 SMCLK 1MHz

    >  UCB0BRW = 0;

    您应该删除第二行、它(重新)将 I2C 时钟设置为1MHz。