Tinkering TI MSP430F5529

USCI – SPI – I2C Example 1

In this first USCI example, we will see how we can use USCI modules to read a MMA7455L accelerometer in I2C mode and project its readings on a SPI-based ST7735 TFT display. This is an over simplified example and a rudimentary one although it may appear that lot of coding has been done here. Here, the accelerometer’s axes readings are plotted on the TFT display.

Code Example

MMA7455L.h

#include "driverlib.h"
#include "delay.h"

#define I2C_port                             GPIO_PORT_P4

#define I2C_SDA_pin                          GPIO_PIN1
#define I2C_SCL_pin                          GPIO_PIN2

#define MMA7455L_address                     0x1D
                                                
#define MMA7455L_X_out_L                     0x00  
#define MMA7455L_X_out_H                     0x01  
#define MMA7455L_Y_out_L                     0x02  
#define MMA7455L_Y_out_H                     0x03    
#define MMA7455L_Z_out_L                     0x04  
#define MMA7455L_Z_out_H                     0x05    
#define MMA7455L_X_out                       0x06    
#define MMA7455L_Y_out                       0x07  
#define MMA7455L_Z_out                       0x08      
#define MMA7455L_STATUS                      0x09  
#define MMA7455L_DETSRC                      0x0A  
#define MMA7455L_TOUT                        0x0B
#define MMA7455L_RSV1                        0x0C
#define MMA7455L_I2C_Address                 0x0D
#define MMA7455L_User_Info                   0x0E
#define MMA7455L_Who_Am_I                    0x0F
#define MMA7455L_X_offset_L                  0x10  
#define MMA7455L_X_offset_H                  0x11  
#define MMA7455L_Y_offset_L                  0x12  
#define MMA7455L_Y_offset_H                  0x13    
#define MMA7455L_Z_offset_L                  0x14  
#define MMA7455L_Z_offset_H                  0x15 
#define MMA7455L_MCTL                        0x16
#define MMA7455L_INTRST                      0x17
#define MMA7455L_CTL1                        0x18
#define MMA7455L_CTL2                        0x19
#define MMA7455L_LDTH                        0x1A
#define MMA7455L_PDTH                        0x1B
#define MMA7455L_PW                          0x1C
#define MMA7455L_LT                          0x1D
#define MMA7455L_TW                          0x1E
#define MMA7455L_RSV2                        0x1F    

#define MMA_7455_2G_MODE                     0x05 
#define MMA_7455_4G_MODE                     0x09     
#define MMA_7455_8G_MODE                     0x01

void I2C_DIO_init(void);
void USCI_I2C_init(void);
void MMA7455L_init(void);
void MMA7455L_write_byte(unsigned char address, unsigned char value);
void MMA7455L_write_word(unsigned char address, unsigned int value);
unsigned char MMA7455L_read_byte(unsigned char address);
unsigned int MMA7455L_read_word(unsigned char address);
signed char MMA7455L_read_axis_8(unsigned char axis);
signed int MMA7455L_read_axis_10(unsigned char axis);

MMA7455L.c

#include "MMA7455L.h"

void I2C_DIO_init(void)
{
    GPIO_setAsPeripheralModuleFunctionOutputPin(I2C_port, (I2C_SDA_pin | I2C_SCL_pin));
}

void USCI_I2C_init(void)
{
    USCI_B_I2C_initMasterParam I2C_param = {0};

    I2C_DIO_init();

    I2C_param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    I2C_param.i2cClk = UCS_getSMCLK();
    I2C_param.dataRate = USCI_B_I2C_SET_DATA_RATE_100KBPS;

    USCI_B_I2C_initMaster(USCI_B1_BASE, &I2C_param);

    USCI_B_I2C_enable(USCI_B1_BASE);
}

void MMA7455L_init(void)
{
    USCI_I2C_init();  
    MMA7455L_write_byte(MMA7455L_CTL1, 0x80);
    MMA7455L_write_byte(MMA7455L_MCTL, MMA_7455_2G_MODE);
}

void MMA7455L_write_byte(unsigned char address, unsigned char value)
{
    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);

    USCI_B_I2C_masterSendMultiByteStart(USCI_B1_BASE, address);
    while(!USCI_B_I2C_masterIsStartSent(USCI_B1_BASE));
    USCI_B_I2C_masterSendMultiByteFinish(USCI_B1_BASE, value);

    while(USCI_B_I2C_isBusBusy(USCI_B1_BASE));
}

void MMA7455L_write_word(unsigned char address, unsigned int value)
{
    unsigned char lb = 0x00;
    unsigned char hb = 0x00;

    lb = ((unsigned char)value);
    value >>= 8;
    hb = ((unsigned char)value);

    MMA7455L_write_byte(address, lb);
    MMA7455L_write_byte((address + 1), hb);
}

unsigned char MMA7455L_read_byte(unsigned char address)
{
    unsigned char value = 0x00;

    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);

    USCI_B_I2C_masterSendStart(USCI_B1_BASE);
    USCI_B_I2C_masterSendSingleByte(USCI_B1_BASE, address);

    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);

    USCI_B_I2C_masterReceiveSingleStart(USCI_B1_BASE);
    value = USCI_B_I2C_masterReceiveSingle(USCI_B1_BASE);

    while(USCI_B_I2C_isBusBusy(USCI_B1_BASE));

    return value;
}

unsigned int MMA7455L_read_word(unsigned char address)
{
    unsigned char lb = 0x00;
    unsigned int hb = 0x0000;

    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);

    USCI_B_I2C_masterSendStart(USCI_B1_BASE);
    USCI_B_I2C_masterSendSingleByte(USCI_B1_BASE, address);

    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);

    USCI_B_I2C_masterReceiveMultiByteStart(USCI_B1_BASE);
    lb = USCI_B_I2C_masterReceiveMultiByteNext(USCI_B1_BASE);
    hb = USCI_B_I2C_masterReceiveMultiByteFinish(USCI_B1_BASE);

    USCI_B_I2C_masterReceiveMultiByteStop(USCI_B1_BASE);

    while(USCI_B_I2C_isBusBusy(USCI_B1_BASE));

    hb <<= 8;
    hb |= lb;

    return hb;
}

signed char MMA7455L_read_axis_8(unsigned char axis)
{
    return ((signed char)MMA7455L_read_byte(axis));
}

signed int MMA7455L_read_axis_10(unsigned char axis)
{
    return ((signed int)MMA7455L_read_word(axis) & 0x03FF);
}

ST7735.h

#include "driverlib.h"
#include "delay.h"

#define MOSI_port                               GPIO_PORT_P3
#define MISO_port                               GPIO_PORT_P3
#define CLK_port                                GPIO_PORT_P3
#define RST_port                                GPIO_PORT_P3
#define RS_port                                 GPIO_PORT_P3
#define CS_port                                 GPIO_PORT_P3

#define MOSI_pin                                GPIO_PIN0
#define MISO_pin                                GPIO_PIN1
#define CLK_pin                                 GPIO_PIN2
#define RST_pin                                 GPIO_PIN3
#define RS_pin                                  GPIO_PIN4
#define CS_pin                                  GPIO_PIN5

#define MOSI_pin_high() GPIO_setOutputHighOnPin(MOSI_port, MOSI_pin)
#define MOSI_pin_low()  GPIO_setOutputLowOnPin(MOSI_port, MOSI_pin)

#define get_MISO_pin()  GPIO_getInputPinValue(MISO_port, MISO_pin)

#define CLK_pin_high()  GPIO_setOutputHighOnPin(CLK_port, CLK_pin)
#define CLK_pin_low()   GPIO_setOutputLowOnPin(CLK_port, CLK_pin)

#define RST_pin_high()  GPIO_setOutputHighOnPin(RST_port, RST_pin)
#define RST_pin_low()   GPIO_setOutputLowOnPin(RST_port, RST_pin)

#define RS_pin_high()   GPIO_setOutputHighOnPin(RS_port, RS_pin)
#define RS_pin_low()    GPIO_setOutputLowOnPin(RS_port, RS_pin)

#define CS_pin_high()   GPIO_setOutputHighOnPin(CS_port, CS_pin)
#define CS_pin_low()    GPIO_setOutputLowOnPin(CS_port, CS_pin)

#define ST7735_NOP                              0x00
#define ST7735_SWRESET                          0x01
#define ST7735_RDDID                            0x04
#define ST7735_RDDST                            0x09
#define ST7735_RDDPM                            0x0A
#define ST7735_RDD_MADCTL                       0x0B
#define STT7735_RDD_COLMOD                      0x0C
#define ST7735_RDDIM                            0x0D
#define ST7735_RDDSM                            0x0E

#define ST7735_SLPIN                            0x10
#define ST7735_SLPOUT                           0x11
#define ST7735_PTLON                            0x12
#define ST7735_NORON                            0x13

#define ST7735_INVOFF                           0x20
#define ST7735_INVON                            0x21
#define ST7735_GAMSET                           0x26
#define ST7735_DISPOFF                          0x28
#define ST7735_DISPON                           0x29
#define ST7735_CASET                            0x2A
#define ST7735_RASET                            0x2B
#define ST7735_RAMWR                            0x2C
#define ST7735_RAMRD                            0x2E

#define ST7735_PTLAR                            0x30
#define ST7735_TEOFF                            0x34
#define ST7735_TEON                             0x35
#define ST7735_MADCTL                           0x36
#define ST7735_IDMOFF                           0x38
#define ST7735_IDMON                            0x39
#define ST7735_COLMOD                           0x3A

#define ST7735_RDID1                            0xDA
#define ST7735_RDID2                            0xDB
#define ST7735_RDID3                            0xDC
#define ST7735_RDID4                            0xDD

#define ST7735_FRMCTR1                          0xB1
#define ST7735_FRMCTR2                          0xB2
#define ST7735_FRMCTR3                          0xB3
#define ST7735_INVCTR                           0xB4
#define ST7735_DISSET5                          0xB6

#define ST7735_PWCTR1                           0xC0
#define ST7735_PWCTR2                           0xC1
#define ST7735_PWCTR3                           0xC2
#define ST7735_PWCTR4                           0xC3
#define ST7735_PWCTR5                           0xC4
#define ST7735_VMCTR1                           0xC5

#define ST7735_RDID1                            0xDA
#define ST7735_RDID2                            0xDB
#define ST7735_RDID3                            0xDC
#define ST7735_RDID4                            0xDD

#define ST7735_PWCTR6                           0xFC

#define ST7735_GMCTRP1                          0xE0
#define ST7735_GMCTRN1                          0xE1

#define BLACK                                   0x0000
#define BLUE                                    0x001F
#define RED                                     0xF800
#define GREEN                                   0x07E0
#define CYAN                                    0x07FF
#define MAGENTA                                 0xF81F
#define YELLOW                                  0xFFE0
#define WHITE                                   0xFFFF

#define MADCTL_MY                               0x80
#define MADCTL_MX                               0x40
#define MADCTL_MV                               0x20
#define MADCTL_ML                               0x10
#define MADCTL_RGB                              0x08
#define MADCTL_MH                               0x04

#define ST7735_TFTWIDTH                         128
#define ST7735_TFTLENGTH                        160

#define CMD                                     0
#define DAT                                     1

#define SQUARE                                  0
#define ROUND                                   1

#define NO                                      0
#define YES                                     1

void SPI_DIO_init(void);
void USCI_SPI_init(void);
void ST7735_init(void);
void ST7735_Write(unsigned char value, unsigned char mode);
void ST7735_Reset(void);
void ST7735_Word_Write(unsigned int value);
void ST7735_Data_Write(unsigned char DataH, unsigned char DataL);
void ST7735_Data_Write_4k(unsigned char DataH, unsigned char DataM, unsigned char DataL);
void ST7735_Set_Addr_Window(unsigned char xs, unsigned char ys, unsigned char xe, unsigned char ye);
void ST7735_RAM_Address_Set(void);
void ST7735_Invert_Display(unsigned char i);
unsigned int ST7735_Swap_Colour(unsigned int colour);
unsigned int ST7735_Color565(unsigned char r, unsigned char g, unsigned char b);
void ST7735_Set_Rotation(unsigned char m);
void TFT_fill(unsigned int colour);
void Draw_Pixel(unsigned char x_pos, unsigned char y_pos, unsigned int colour);
void Draw_Line(signed int x1, signed int y1, signed int x2, signed int y2, unsigned int colour);
void Draw_Rectangle(signed int x1, signed int y1, signed int x2, signed int y2, unsigned char fill, unsigned char type, unsigned int colour, unsigned int back_colour);
void Draw_Circle(signed int xc, signed int yc, signed int radius, unsigned char fill, unsigned int colour);
void Draw_Font_Pixel(unsigned char x_pos, unsigned char y_pos, unsigned int colour, unsigned char pixel_size);
void print_char(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, unsigned char ch);
void print_str(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, unsigned char *ch);
void print_C(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, signed int value);
void print_I(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, signed int value);
void print_D(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, unsigned int value, unsigned char points);
void print_F(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, float value, unsigned char points);

ST7735.c

#include "ST7735.h"

static const unsigned char fonts[96][5] =
{
     {0x00, 0x00, 0x00, 0x00, 0x00} // 20
    ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
    ,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
    ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
    ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
    ,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
    ,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
    ,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
    ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
    ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
    ,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
    ,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
    ,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
    ,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
    ,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
    ,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
    ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
    ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
    ,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
    ,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
    ,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
    ,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
    ,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
    ,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
    ,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
    ,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
    ,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
    ,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
    ,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c 
    ,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
    ,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
    ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
    ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
    ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
    ,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
    ,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
    ,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
    ,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
    ,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
    ,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
    ,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
    ,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
    ,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
    ,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
    ,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
    ,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
    ,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
    ,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
    ,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
    ,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
    ,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
    ,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
    ,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
    ,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
    ,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
    ,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
    ,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
    ,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
    ,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ?
    ,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
    ,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
    ,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
    ,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
    ,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
    ,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
    ,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
    ,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
    ,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
    ,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
    ,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
    ,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
    ,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
    ,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
    ,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
    ,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
    ,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
    ,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
    ,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
    ,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
    ,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
    ,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
    ,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
    ,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
    ,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
    ,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
    ,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
    ,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
    ,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
    ,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
    ,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
    ,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
    ,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
    ,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ?
    ,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f ?
};

static unsigned char width = ST7735_TFTWIDTH;
static unsigned char length = ST7735_TFTLENGTH;


void SPI_DIO_init(void)
{
    GPIO_setAsPeripheralModuleFunctionInputPin(MISO_port, MISO_pin);

    GPIO_setAsPeripheralModuleFunctionOutputPin(MOSI_port, MOSI_pin);
    GPIO_setAsPeripheralModuleFunctionOutputPin(CLK_port, CLK_pin);

    GPIO_setAsOutputPin(RST_port, RST_pin);
    GPIO_setDriveStrength(RST_port, RST_pin, GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsOutputPin(RS_port, RS_pin);
    GPIO_setDriveStrength(RS_port, RS_pin, GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsOutputPin(CS_port, CS_pin);
    GPIO_setDriveStrength(CS_port, CS_pin, GPIO_FULL_OUTPUT_DRIVE_STRENGTH);
}

void USCI_SPI_init(void)
{
    USCI_B_SPI_initMasterParam SPI_param = {0};

    SPI_DIO_init();

    SPI_param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK;
    SPI_param.clockSourceFrequency = UCS_getSMCLK();
    SPI_param.desiredSpiClock = 2000000;
    SPI_param.msbFirst = USCI_B_SPI_MSB_FIRST;
    SPI_param.clockPhase = USCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
    SPI_param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
    
    USCI_B_SPI_initMaster(USCI_B0_BASE, &SPI_param);

    USCI_B_SPI_enable(USCI_B0_BASE);
}

void ST7735_init(void)
{
    USCI_SPI_init();
    
    ST7735_Reset();
    
    ST7735_Write(ST7735_SWRESET, CMD);
    delay_us(150);
    ST7735_Write(ST7735_SLPOUT, CMD);
    delay_us(150);

    ST7735_Write(ST7735_FRMCTR1, CMD);
    ST7735_Write(0x01, DAT);
    ST7735_Write(0x2C, DAT);
    ST7735_Write(0x2D, DAT);
    
    ST7735_Write(ST7735_FRMCTR2, CMD);
    ST7735_Write(0x01, DAT);
    ST7735_Write(0x2C, DAT);
    ST7735_Write(0x2D, DAT);
    
    ST7735_Write(ST7735_FRMCTR3, CMD);
    ST7735_Write(0x01, DAT);
    ST7735_Write(0x2C, DAT); 
    ST7735_Write(0x2D, DAT);
    ST7735_Write(0x01, DAT);
    ST7735_Write(0x2C, DAT);
    ST7735_Write(0x2D, DAT);

    ST7735_Write(ST7735_INVCTR, CMD);
    ST7735_Write(0x07, DAT);

    ST7735_Write(ST7735_PWCTR1, CMD);
    ST7735_Write(0xA2, DAT); 
    ST7735_Write(0x02, DAT); 
    ST7735_Write(0x84, DAT);

    ST7735_Write(ST7735_PWCTR1, CMD);
    ST7735_Write(0xC5, DAT);

    ST7735_Write(ST7735_PWCTR2, CMD);
    ST7735_Write(0x0A, DAT);
    ST7735_Write(0x00, DAT);

    ST7735_Write(ST7735_PWCTR3, CMD);
    ST7735_Write(0x8A, DAT);
    ST7735_Write(0x2A, DAT);

    ST7735_Write(ST7735_PWCTR4, CMD);
    ST7735_Write(0x8A, DAT);
    ST7735_Write(0xEE, DAT);

    ST7735_Write(ST7735_PWCTR5, CMD);
    ST7735_Write(0x0E, DAT);

    ST7735_Write(ST7735_VMCTR1, CMD);
    ST7735_Write(0x00, DAT);

    ST7735_Write(ST7735_COLMOD, CMD);
    ST7735_Write(0x05, DAT);

    ST7735_Write(ST7735_MADCTL, CMD);
    ST7735_Write(0xC8, DAT);
    
    ST7735_RAM_Address_Set();
    
    ST7735_Write(ST7735_GMCTRP1, CMD);
    ST7735_Write(0x02, DAT);
    ST7735_Write(0x1C, DAT);
    ST7735_Write(0x07, DAT);
    ST7735_Write(0x12, DAT);
    ST7735_Write(0x37, DAT);
    ST7735_Write(0x32, DAT);
    ST7735_Write(0x29, DAT);
    ST7735_Write(0x2D, DAT);
    ST7735_Write(0x29, DAT);
    ST7735_Write(0x25, DAT);
    ST7735_Write(0x2B, DAT);
    ST7735_Write(0x39, DAT);
    ST7735_Write(0x00, DAT);
    ST7735_Write(0x01, DAT);
    ST7735_Write(0x03, DAT);
    ST7735_Write(0x10, DAT);
    
    ST7735_Write(ST7735_GMCTRN1, CMD);
    ST7735_Write(0x03, DAT);
    ST7735_Write(0x1D, DAT);
    ST7735_Write(0x07, DAT);
    ST7735_Write(0x06, DAT);
    ST7735_Write(0x2E, DAT);
    ST7735_Write(0x2C, DAT);
    ST7735_Write(0x29, DAT);
    ST7735_Write(0x2D, DAT);
    ST7735_Write(0x2E, DAT);
    ST7735_Write(0x2E, DAT);
    ST7735_Write(0x37, DAT);
    ST7735_Write(0x3F, DAT);
    ST7735_Write(0x00, DAT);
    ST7735_Write(0x00, DAT);
    ST7735_Write(0x02, DAT);
    ST7735_Write(0x10, DAT);

    ST7735_Write(ST7735_NORON, CMD);
    delay_ms(10);

    ST7735_Write(ST7735_DISPON, CMD);
    delay_ms(100);
    
    ST7735_Write(ST7735_RAMWR, CMD);
    delay_ms(100);
}

void ST7735_Write(unsigned char value, unsigned char mode)
{
    CS_pin_low();
    
    if(mode != 0)
    {
        RS_pin_high();
    }
    else
    {
        RS_pin_low();
    }

    USCI_B_SPI_transmitData(USCI_B0_BASE, value);
    while(USCI_B_SPI_isBusy(USCI_B0_BASE));
    
    CS_pin_high();
}

void ST7735_Reset(void)
{
    RST_pin_low();
    delay_ms(2);
    RST_pin_high();
    delay_ms(2);
}

void ST7735_Word_Write(unsigned int value)
{
    ST7735_Write(((value & 0xFF00) >> 0x08), DAT);
    ST7735_Write((value & 0x00FF), DAT);
}

void ST7735_Data_Write(unsigned char DataH, unsigned char DataL)
{
    ST7735_Write(DataH, DAT);
    ST7735_Write(DataL, DAT);
}

void ST7735_Data_Write_4k(unsigned char DataH, unsigned char DataM, unsigned char DataL)
{
    ST7735_Write(DataH, DAT);
    ST7735_Write(DataM, DAT);
    ST7735_Write(DataL, DAT);
}

void ST7735_Set_Addr_Window(unsigned char xs, unsigned char ys, unsigned char xe, unsigned char ye)
{
    ST7735_Write(ST7735_CASET, CMD);
    ST7735_Write(0x00, DAT);
    ST7735_Write(xs, DAT);
    ST7735_Write(0x00, DAT);
    ST7735_Write(xe, DAT);

    ST7735_Write(ST7735_RASET, CMD);
    ST7735_Write(0x00, DAT);
    ST7735_Write(ys, DAT);
    ST7735_Write(0x00, DAT);
    ST7735_Write(ye, DAT);

    ST7735_Write(ST7735_RAMWR, CMD);
}

void ST7735_RAM_Address_Set(void)
{
    ST7735_Set_Addr_Window(0x00, 0x00, 0x7F, 0x9F);
}

void ST7735_Invert_Display(unsigned char i)
{
     if(i == ST7735_INVON)
     {
         ST7735_Write(ST7735_INVON, CMD);
     }
     else
     {
         ST7735_Write(ST7735_INVOFF, CMD);
     }
}

unsigned int ST7735_Swap_Colour(unsigned int colour)
{
    return ((colour <> 0x000B));
}

unsigned int ST7735_Color565(unsigned char r, unsigned char g, unsigned char b)
{
    return (((r & 0xF8) << 0x08) | ((g & 0xFC) <> 0x03));
}

void ST7735_Set_Rotation(unsigned char m)
{
    unsigned char rotation = 0x00;

    ST7735_Write(ST7735_MADCTL, CMD);
    rotation = (m % 4);
    
    switch(rotation)
    {
        case 0:
        {
            ST7735_Write((MADCTL_MX | MADCTL_MY | MADCTL_RGB), DAT);
            width = ST7735_TFTWIDTH;
            length = ST7735_TFTLENGTH;
            break;
        }
        case 1:
        {
            ST7735_Write((MADCTL_MY | MADCTL_MV | MADCTL_RGB), DAT);
            width = ST7735_TFTLENGTH;
            length = ST7735_TFTWIDTH;
            break;
        }
        case 2:
        {
            ST7735_Write((MADCTL_RGB), DAT);
            width = ST7735_TFTWIDTH;
            length = ST7735_TFTLENGTH;
            break;
        }
        case 3:
        {
            ST7735_Write((MADCTL_MX | MADCTL_MV | MADCTL_RGB), DAT);
            width = ST7735_TFTLENGTH;
            length = ST7735_TFTWIDTH;
            break;
        }
    }
}

void TFT_fill(unsigned int colour)
{
    unsigned char i = 0x00;
    unsigned char j = 0x00;

    ST7735_Set_Addr_Window(0, 0, (width - 1), (length - 1));

    for(j = length; j > 0; j--)
    {
        for(i = width; i > 0; i--)
        {
            ST7735_Word_Write(colour);
        }
    }
}

void Draw_Pixel(unsigned char x_pos, unsigned char y_pos, unsigned int colour)
{
    ST7735_Set_Addr_Window(x_pos, y_pos, (1 + x_pos), (1 + y_pos));
     ST7735_Word_Write(colour);
}

void Draw_Line(signed int x1, signed int y1, signed int x2, signed int y2, unsigned int colour)
{
    signed int dx = 0x0000;
    signed int dy = 0x0000;
    signed int stepx = 0x0000;
    signed int stepy = 0x0000;
    signed int fraction = 0x0000;

    dy = (y2 - y1);
    dx = (x2 - x1);

    if (dy < 0)
    {
        dy = -dy;
        stepy = -1;
    }
    else
    {
        stepy = 1;
    }

    if (dx < 0)
    {
        dx = -dx;
        stepx = -1;
    }
    else
    {
        stepx = 1;
    }

    dx <<= 0x01;
    dy < dy)
    {
        fraction = (dy - (dx >> 1));
        while (x1 != x2)
        {
            if (fraction >= 0)
            {
                y1 += stepy;
                fraction -= dx;
            }
            x1 += stepx;
            fraction += dy;

            Draw_Pixel(x1, y1, colour);
        }
    }
    else
    {
        fraction = (dx - (dy >> 1));

        while (y1 != y2)
        {
            if (fraction >= 0)
            {
                x1 += stepx;
                fraction -= dy;
            }
            y1 += stepy;
            fraction += dx;
            Draw_Pixel(x1, y1, colour);
        }
    }
}

void Draw_Rectangle(signed int x1, signed int y1, signed int x2, signed int y2, unsigned char fill, unsigned char type, unsigned int colour, unsigned int back_colour)
{
     unsigned char i = 0x00;
     unsigned char xmin = 0x00;
     unsigned char xmax = 0x00;
     unsigned char ymin = 0x00;
     unsigned char ymax = 0x00;

     if(fill != NO)
     {
        if(x1 < x2)
        {
           xmin = x1;
           xmax = x2;
        }
        else
        {
           xmin = x2;
           xmax = x1;
        }

        if(y1 < y2)
        {
           ymin = y1;
           ymax = y2;
        }
        else
        {
           ymin = y2;
           ymax = y1;
        }

        for(; xmin <= xmax; ++xmin)
        {
             for(i = ymin; i <= ymax; ++i)
             {
                 Draw_Pixel(xmin, i, colour);
             }
         }
     }

     else
     {
        Draw_Line(x1, y1, x2, y1, colour);
        Draw_Line(x1, y2, x2, y2, colour);
        Draw_Line(x1, y1, x1, y2, colour);
        Draw_Line(x2, y1, x2, y2, colour);
     }

     if(type != SQUARE)
     {
         Draw_Pixel(x1, y1, back_colour);
         Draw_Pixel(x1, y2, back_colour);
         Draw_Pixel(x2, y1, back_colour);
         Draw_Pixel(x2, y2, back_colour);
     }
}

void Draw_Circle(signed int xc, signed int yc, signed int radius, unsigned char fill, unsigned int colour)
{
   signed int a = 0x0000;
   signed int b = 0x0000;
   signed int p = 0x0000;

   b = radius;
   p = (1 - b);

   do
   {
        if(fill != NO)
        {
            Draw_Line((xc - a), (yc + b), (xc + a), (yc + b), colour);
            Draw_Line((xc - a), (yc - b), (xc + a), (yc - b), colour);
            Draw_Line((xc - b), (yc + a), (xc + b), (yc + a), colour);
            Draw_Line((xc - b), (yc - a), (xc + b), (yc - a), colour);
        }
        else
        {
            Draw_Pixel((xc + a), (yc + b), colour);
            Draw_Pixel((xc + b), (yc + a), colour);
            Draw_Pixel((xc - a), (yc + b), colour);
            Draw_Pixel((xc - b), (yc + a), colour);
            Draw_Pixel((xc + b), (yc - a), colour);
            Draw_Pixel((xc + a), (yc - b), colour);
            Draw_Pixel((xc - a), (yc - b), colour);
            Draw_Pixel((xc - b), (yc - a), colour);
        }

        if(p < 0)
        {
            p += (0x03 + (0x02 * a++));
        }
        else
        {
            p += (0x05 + (0x02 * ((a++) - (b--))));
        }
    }while(a <= b);
}

void Draw_Font_Pixel(unsigned char x_pos, unsigned char y_pos, unsigned int colour, unsigned char pixel_size)
{
     unsigned char i = 0x00;

     ST7735_Set_Addr_Window(x_pos, y_pos, (x_pos + pixel_size - 1), (y_pos + pixel_size - 1));

     for(i = 0x00; i < (pixel_size * pixel_size); i++)
     {
         ST7735_Word_Write(colour);
     }
}

void print_char(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, unsigned char ch)
{
     unsigned char i = 0x00;
     unsigned char j = 0x00;

     unsigned char value = 0x00;

     if(font_size < 1)
     {
         font_size = 1;
     }

     if(x_pos < font_size)
     {
         x_pos = font_size;
     }

     for (i = 0x00; i < 0x05; i++)
     {
         for (j = 0x00; j > j)  & 0x01)
             {
                 Draw_Font_Pixel(x_pos, y_pos, colour, font_size);
             }
             else
             {
                 Draw_Font_Pixel(x_pos, y_pos, back_colour, font_size);
             }

             y_pos = y_pos + font_size;
          }
          y_pos -= (font_size < width)
      {
          x_pos = (font_size + 0x01);
          y_pos += (font_size <= 0x20) && (*ch <= 0x7F));
}

void print_C(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, signed int value)
{
    unsigned char ch[5] = {0x20, 0x20, 0x20, 0x20, 0x20};

     if(value  99) && (value  9) && (value = 0) && (value <= 9))
     {
         ch[1] = ((value % 10) + 0x30);
         ch[2] = 0x20;
         ch[3] = 0x20;
     }

     print_str(x_pos, y_pos, font_size, colour, back_colour, ch);
}

void print_I(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, signed int value)
{
    unsigned char ch[7] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};

    if(value  9999)
    {
        ch[1] = ((value / 10000) + 0x30);
        ch[2] = (((value % 10000)/ 1000) + 0x30);
        ch[3] = (((value % 1000) / 100) + 0x30);
        ch[4] = (((value % 100) / 10) + 0x30);
        ch[5] = ((value % 10) + 0x30);
    }

    else if((value > 999) && (value  99) && (value  9) && (value  1)
    {
        ch[2] = (((value % 1000) / 100) + 0x30);

        if(points > 2)
        {
            ch[3] = (((value % 100) / 10) + 0x30);

            if(points > 3)
            {
                ch[4] = ((value % 10) + 0x30);
            }
        }
    }

    print_str(x_pos, y_pos, font_size, colour, back_colour, ch);
}

void print_F(unsigned char x_pos, unsigned char y_pos, unsigned char font_size, unsigned int colour, unsigned int back_colour, float value, unsigned char points)
{
    signed long tmp = 0x0000;

    tmp = (signed long)value;
    print_I(x_pos, y_pos, font_size, colour, back_colour, tmp);
    tmp = ((signed long)((value - (float)tmp) * 10000));

    if(tmp = 10000) && (value = 1000) && (value = 100) && (value = 10) && (value < 100))
    {
        print_D((x_pos + (0x12 * font_size)), y_pos, font_size, colour, back_colour, tmp, points);
    }
    else if(value < 10)
    {
        print_D((x_pos + (0x0C * font_size)), y_pos, font_size, colour, back_colour, tmp, points);

        if((value) < 0)
        {
            print_char(x_pos, y_pos, font_size, colour, back_colour, 0x2D);
        }
        else
        {
            print_char(x_pos, y_pos, font_size, colour, back_colour, 0x20);
        }
    }
}

main.c

#include "driverlib.h"
#include "delay.h"
#include "ST7735.h"
#include "MMA7455L.h"

void clock_init(void);

void main(void)
{
    signed char x_axis_8 = 0;
    signed char y_axis_8 = 0;
    signed char z_axis_8 = 0;

    WDT_A_hold(WDT_A_BASE);

    clock_init();
    ST7735_init();
    MMA7455L_init();

    ST7735_Set_Rotation(0x02);
    TFT_fill(BLACK);

    print_str(1, 100, 1, GREEN, BLACK, "X8:");
    print_str(1, 110, 1, GREEN, BLACK, "Y8:");
    print_str(1, 120, 1, GREEN, BLACK, "Z8:");


    GPIO_setAsOutputPin(GPIO_PORT_P4,
                        GPIO_PIN7);

    GPIO_setDriveStrength(GPIO_PORT_P4,
                          GPIO_PIN7,
                          GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    while(1)
    {
        x_axis_8 = MMA7455L_read_axis_8(MMA7455L_X_out);
        y_axis_8 = MMA7455L_read_axis_8(MMA7455L_Y_out);
        z_axis_8 = MMA7455L_read_axis_8(MMA7455L_Z_out);

        print_C(45, 100, 1, GREEN, BLACK, x_axis_8);
        print_C(45, 110, 1, GREEN, BLACK, y_axis_8);
        print_C(45, 120, 1, GREEN, BLACK, z_axis_8);

        Draw_Circle(x_axis_8, x_axis_8, 2, YES, CYAN);

        GPIO_toggleOutputOnPin(GPIO_PORT_P4,
                               GPIO_PIN7);

        delay_ms(100);

        Draw_Circle(x_axis_8, x_axis_8, 2, YES, BLACK);
    };
}

void clock_init(void)
{
    PMM_setVCore(PMM_CORE_LEVEL_3);

    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
                                               (GPIO_PIN4 | GPIO_PIN2));

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5,
                                                (GPIO_PIN5 | GPIO_PIN3));

    UCS_setExternalClockSource(XT1_FREQ,
                               XT2_FREQ);

    UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);

    UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,
                    UCS_XCAP_3);

    UCS_initClockSignal(UCS_FLLREF,
                        UCS_XT2CLK_SELECT,
                        UCS_CLOCK_DIVIDER_4);

    UCS_initFLLSettle(MCLK_KHZ,
                      MCLK_FLLREF_RATIO);

    UCS_initClockSignal(UCS_SMCLK,
                        UCS_XT2CLK_SELECT,
                        UCS_CLOCK_DIVIDER_4);

    UCS_initClockSignal(UCS_ACLK,
                        UCS_XT1CLK_SELECT,
                        UCS_CLOCK_DIVIDER_1);
}

Hardware Setup

Explanation

Let’s check the I2C functions of USCI first. USCI B1 is used in I2C mode here. We start by setting alternative roles of I2C GPIO pins as shown below:

GPIO_setAsPeripheralModuleFunctionOutputPin(I2C_port, (I2C_SDA_pin | I2C_SCL_pin));

After setting the I2C pins, the I2C hardware is ready to be initialized.

void USCI_I2C_init(void)
{
    USCI_B_I2C_initMasterParam I2C_param = {0};

    I2C_DIO_init();

    I2C_param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    I2C_param.i2cClk = UCS_getSMCLK();
    I2C_param.dataRate = USCI_B_I2C_SET_DATA_RATE_100KBPS;

    USCI_B_I2C_initMaster(USCI_B1_BASE, &I2C_param);

    USCI_B_I2C_enable(USCI_B1_BASE);
}

For initialization, we need to set I2C module’s clock source first. In this case, the clock source is SMCLK. SMCLK, in this example, is running at 1 MHz as it is being sourced by prescaled XT2 clock source.

UCS_initClockSignal(UCS_SMCLK, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_4);

We have to let the USCI I2C module know the speed of SMCLK and decide our I2C clock rate. Internal mechanism scales the I2C clock source to match the desired I2C data clock rate. Here we set the clock rate to 100 kbps.

After setting all these, we enable the USCI I2C module.

Note that no interrupt has been used as polling is good enough for basic I2C communication.

Now let’s check I2C write operations. Shown below are two types of I2C write operation functions. The first one is coded with driverlib and the other is what we usually do in other microcontrollers and in other software platforms. These are shown to highlight key differences.

void MMA7455L_write_byte(unsigned char address, unsigned char value)
{
    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);

    USCI_B_I2C_masterSendMultiByteStart(USCI_B1_BASE, address);
    while(!USCI_B_I2C_masterIsStartSent(USCI_B1_BASE));
    USCI_B_I2C_masterSendMultiByteFinish(USCI_B1_BASE, value);

    while(USCI_B_I2C_isBusBusy(USCI_B1_BASE));
}

The driverlib-based I2C write operation hides several stuffs in contrast to the operation shown below:

void MMA7455L_write_byte(unsigned char address, unsigned char value)
{
    I2C_Start();                
    I2C_Write(MMA7455L_write_address); 
    I2C_Write(address);              
    I2C_Write(value);   
    I2C_Stop();  
    delay_ms(250);
}

Firstly, there is no I2C start and stop command in driverlib as these are hidden and done internally under the hood of driverlib functions. Secondly, we have to mention in our code if the I2C mode of data transaction is a transmission or a reception. Lastly, the I2C bus is polled for I2C bus status. The polling loops till the bus is free. I believe these differences are clear now.

Now let’s see the I2C read operations. Just like the write operations, we will again check differences between driverlib and conventional I2C bus reading method.

unsigned char MMA7455L_read_byte(unsigned char address)
{
    unsigned char value = 0x00;

    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);

    USCI_B_I2C_masterSendStart(USCI_B1_BASE);
    USCI_B_I2C_masterSendSingleByte(USCI_B1_BASE, address);

    USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, MMA7455L_address);
    USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);

    USCI_B_I2C_masterReceiveSingleStart(USCI_B1_BASE);
    value = USCI_B_I2C_masterReceiveSingle(USCI_B1_BASE);

    while(USCI_B_I2C_isBusBusy(USCI_B1_BASE));

    return value;
}

The code snippet below shows conventional I2C bus read:

unsigned char MMA7455L_read_byte(unsigned char address)   
{   
    unsigned char value = 0;
   
    I2C_Start();                                   
    I2C_Write(MMA7455L_write_address);                                            
    I2C_Write(address); 

    I2C_Restart(); 
    I2C_Write(MMA7455L_read_address); 
    value = I2C_Read(0);                         
    I2C_Stop(); 

    return value;               
}

The key differences between these two code snippets above are similar as the ones we already noticed in I2C write codes. I stated similar because there are some new additions to these already existing differences. Firstly, note that there is no I2C restart or start function in driverlib as sending out slave address incorporates that in secret. Secondly, during an I2C read, there is a transmission and a reception session and so there are two USCI modes in a bus read operation. Lastly, note that read acknowledgement (ACK/NACK) is not manually sent in driverlib as again it is done under the hood.

I believe, by now, the driverlib concepts for I2C are clear.

Since we are using a TFT display as an external SPI device in this example and not reading it, we will just be focusing on SPI write operation only. Firstly, we declare all necessary GPIO pins.

#define MOSI_port                 GPIO_PORT_P3
#define MISO_port                 GPIO_PORT_P3
#define CLK_port                  GPIO_PORT_P3
#define RST_port                  GPIO_PORT_P3
#define RS_port                   GPIO_PORT_P3
#define CS_port                   GPIO_PORT_P3

#define MOSI_pin                  GPIO_PIN0
#define MISO_pin                  GPIO_PIN1
#define CLK_pin                   GPIO_PIN2
#define RST_pin                   GPIO_PIN3
#define RS_pin                    GPIO_PIN4
#define CS_pin                    GPIO_PIN5

#define MOSI_pin_high()           GPIO_setOutputHighOnPin(MOSI_port, MOSI_pin)
#define MOSI_pin_low()            GPIO_setOutputLowOnPin(MOSI_port, MOSI_pin)

#define get_MISO_pin()            GPIO_getInputPinValue(MISO_port, MISO_pin)

#define CLK_pin_high()            GPIO_setOutputHighOnPin(CLK_port, CLK_pin)
#define CLK_pin_low()             GPIO_setOutputLowOnPin(CLK_port, CLK_pin)

#define RST_pin_high()            GPIO_setOutputHighOnPin(RST_port, RST_pin)
#define RST_pin_low()             GPIO_setOutputLowOnPin(RST_port, RST_pin)

#define RS_pin_high()             GPIO_setOutputHighOnPin(RS_port, RS_pin) #define RS_pin_low()              GPIO_setOutputLowOnPin(RS_port, RS_pin)

#define CS_pin_high()             GPIO_setOutputHighOnPin(CS_port, CS_pin)
#define CS_pin_low()              GPIO_setOutputLowOnPin(CS_port, CS_pin)

We, then, initialize the GPIOs as per pin characteristics. SPI pins, just like I2C pins, are initialized as secondary function pins while the rest are initialized as ordinary GPIOs.   

void SPI_DIO_init(void)
{
    GPIO_setAsPeripheralModuleFunctionInputPin(MISO_port, MISO_pin);

    GPIO_setAsPeripheralModuleFunctionOutputPin(MOSI_port, MOSI_pin);
    GPIO_setAsPeripheralModuleFunctionOutputPin(CLK_port, CLK_pin);

    GPIO_setAsOutputPin(RST_port, RST_pin);
    GPIO_setDriveStrength(RST_port, RST_pin, GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsOutputPin(RS_port, RS_pin);
    GPIO_setDriveStrength(RS_port, RS_pin, GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsOutputPin(CS_port, CS_pin);
    GPIO_setDriveStrength(CS_port, CS_pin, GPIO_FULL_OUTPUT_DRIVE_STRENGTH);
}

Next, we initialize the USCI B0 module in SPI mode.

void USCI_SPI_init(void)
{
    USCI_B_SPI_initMasterParam SPI_param = {0};

    SPI_DIO_init();

    SPI_param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK;
    SPI_param.clockSourceFrequency = UCS_getSMCLK();
    SPI_param.desiredSpiClock = 2000000;
    SPI_param.msbFirst = USCI_B_SPI_MSB_FIRST;
    SPI_param.clockPhase = USCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
    SPI_param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
    
    USCI_B_SPI_initMaster(USCI_B0_BASE, &SPI_param);

    USCI_B_SPI_enable(USCI_B0_BASE);
}

The first part SPI module’s initialization is the initialization of required GPIOs.

Like I2C, we have to declare the source of SPI clock (here SMCLK), its frequency and the SPI clock speed. SPI needs additional info like clock polarity, clock phase and data orientation. These are also needed to be set.

After setting all these, we have our USCI SPI module ready to rock-&-roll. 

SPI write is very simple and straight forward. We just have to write desired value(s) and wait for the SPI bus to get free. As we all know, for most SPI devices, chip select pin needs to be low prior to a read/write operation and high after completion of read/write. This is done here too.  

void ST7735_Write(unsigned char value, unsigned char mode)
{
    CS_pin_low();
    
    if(mode != 0)
    {
        RS_pin_high();
    }
    else
    {
        RS_pin_low();
    }

    USCI_B_SPI_transmitData(USCI_B0_BASE, value);
    while(USCI_B_SPI_isBusy(USCI_B0_BASE));
    
    CS_pin_high();
}

The demo here reads a MMA7455L accelerometer and plots a circle on a ST7735 TFT display. The coordinates of the circle are based on the X-Y values of the accelerometer. The accelerometer’s axes values are also displayed.

Demo

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

Related Posts

14 comments

Leave a Reply

Your email address will not be published. Required fields are marked *