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.

TMS320F28379D: SCI_write not working

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Tool/software:

//###########################################################################
/*
 * This is a minimum working example which demonstrates usage of the SCI Module
 * for the MSP430F28379D
 *
 * Pinout
 *
 * I2C :            SDA (J1.10 / GPIO104)
 *                  SCL (J1.9 / GPIO105)
 * SCIA :           GPIO43 / GPIO42 (on board)
 * HEARTBEAT :      GPIO0 (J4.40)
 * ODINT-PIN :      GPIO1 (J4.39)
*/
//#############################################################################

//
// Included Files
//

#include <akm.h>
#include "driverlib.h"
#include "device.h"

#define TIMER_PERIOD_US 2000

uint8_t start_meas=0;
//test string for testing the serial comm
const char teststr[]="NNAABBCC\r\n";
uint16_t sendbuf[12];
uint16_t read_buf[8];
uint8_t is_sof=0;   //indicates whether the last read sample was a start of frame sample

//circular buffer for storing H field samples
//#define CIRCULAR_BUFFER_SIZE 512
//int16_t bit5buffer[CIRCULAR_BUFFER_SIZE];

struct akm_meas{
    int16_t Bx;
    int16_t By;
    int16_t Bz;
    uint16_t status;
};

__interrupt void cpuTimer0ISR(void){
    start_meas=1;
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}


void serialize_akm(uint16_t* dest, const struct akm_meas* meas){
    //first two bytes is 0xFF for a regular sample and 0xAA for a SOF sample
    if(is_sof){
        dest[0]=0x00AA;
        dest[1]=0x00AA;
        dest[2]=0x00AA;
    }
    else{
        dest[0]=0x00FF;
        dest[1]=0x00FF;
        dest[2]=0x00FF;
    }
    //serialized measurements
    dest[3]=0x00FF;// (meas->Bx);
    dest[4]= 0x00FF;// (meas->Bx)>>8;
    dest[5]=0x00;
    dest[6]= 0x00FF;// (meas->By);
    dest[7]= 0x00FF;// (meas->By)>>8;
    dest[8]=0x00;
    dest[9]= 0x00FF;// (meas->Bz);
    dest[10]= 0x00FF;// (meas->Bz)>>8;
    dest[11]=0x00;
}

void init_i2c(void){
    I2C_disableModule(I2CA_BASE);
    I2C_initMaster(I2CA_BASE, DEVICE_SYSCLK_FREQ, 200000, I2C_DUTYCYCLE_50);
    I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
    I2C_setSlaveAddress(I2CA_BASE, 0);
    I2C_disableLoopback(I2CA_BASE);
    I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8);
    I2C_setDataCount(I2CA_BASE, 1);
    I2C_setAddressMode(I2CA_BASE, I2C_ADDR_MODE_7BITS);
    I2C_enableFIFO(I2CA_BASE);
    I2C_setFIFOInterruptLevel(I2CA_BASE, I2C_FIFO_TXEMPTY, I2C_FIFO_RXEMPTY);
    I2C_setEmulationMode(I2CA_BASE, I2C_EMULATION_FREE_RUN);
    I2C_enableModule(I2CA_BASE);
}

void pinmux_init(void){
    // GPIO11 -> HEARTBEAT Pinmux
    GPIO_setPinConfig(GPIO_0_GPIO0);
    GPIO_setDirectionMode(HEARTBEAT_PIN, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(HEARTBEAT_PIN, GPIO_PIN_TYPE_STD);
    GPIO_setMasterCore(HEARTBEAT_PIN, GPIO_CORE_CPU1);
    GPIO_setQualificationMode(HEARTBEAT_PIN, GPIO_QUAL_SYNC);
    // SDA & SCL lines for I2C
    GPIO_setPinConfig(GPIO_105_SCLA);
    GPIO_setPadConfig(105, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(105, GPIO_PIN_TYPE_OD);
    GPIO_setQualificationMode(105, GPIO_QUAL_ASYNC);
    GPIO_setPinConfig(GPIO_104_SDAA);
    GPIO_setPadConfig(104, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(104, GPIO_PIN_TYPE_OD);
    GPIO_setQualificationMode(104, GPIO_QUAL_ASYNC);
    // ODINT Pin
    GPIO_setDirectionMode(ODINT,GPIO_DIR_MODE_IN);
    GPIO_setPinConfig(GPIO_1_GPIO1);
    // SCIA
    GPIO_setPinConfig(GPIO_43_SCIRXDA);
    GPIO_setPinConfig(GPIO_42_SCITXDA);
}

void gpio_init(void){
    //HEARTBEAT initialization
    GPIO_setDirectionMode(HEARTBEAT_PIN, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(HEARTBEAT_PIN, GPIO_PIN_TYPE_STD);
    GPIO_setMasterCore(HEARTBEAT_PIN, GPIO_CORE_CPU1);
    GPIO_setQualificationMode(HEARTBEAT_PIN, GPIO_QUAL_SYNC);
    //start of frame SOF GPIO
    GPIO_setDirectionMode(SOF_GPIO, GPIO_DIR_MODE_IN);
    GPIO_setPadConfig(SOF_GPIO, GPIO_PIN_TYPE_STD);
    GPIO_setMasterCore(SOF_GPIO, GPIO_CORE_CPU1);
    GPIO_setQualificationMode(SOF_GPIO, GPIO_QUAL_SYNC);

    //W2BW_SUPPLY initialization
//    GPIO_setDirectionMode(ODINT, GPIO_DIR_MODE_OUT);
//    GPIO_setPadConfig(ODINT, GPIO_PIN_TYPE_STD);
//    GPIO_setMasterCore(ODINT, GPIO_CORE_CPU1);
//    GPIO_setQualificationMode(ODINT, GPIO_QUAL_SYNC);
}

void timer_init(void){
    const uint32_t timer_perios_us=TIMER_PERIOD_US;
    CPUTimer_setPeriod(CPUTIMER0_BASE,DEVICE_SYSCLK_FREQ/1000000*timer_perios_us);
    CPUTimer_setEmulationMode(CPUTIMER0_BASE,
                              CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
    CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);
    CPUTimer_stopTimer(CPUTIMER0_BASE);
    CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
    CPUTimer_startTimer(CPUTIMER0_BASE);
    //register & enable CPU Timer0 interrupt
    Interrupt_register(INT_TIMER0, &cpuTimer0ISR);
    CPUTimer_enableInterrupt(CPUTIMER0_BASE);
    Interrupt_enable(INT_TIMER0);
}

void sci_comm(void){
    //
    // Configuration for the SCI Rx pin.
    //
    GPIO_setMasterCore(DEVICE_GPIO_PIN_SCIRXDA, GPIO_CORE_CPU1);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDA);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_DIR_MODE_IN);
    GPIO_setPadConfig(DEVICE_GPIO_PIN_SCIRXDA, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_QUAL_ASYNC);

    //
    // Configuration for the SCI Tx pin.
    //
    GPIO_setMasterCore(DEVICE_GPIO_PIN_SCITXDA, GPIO_CORE_CPU1);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDA);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(DEVICE_GPIO_PIN_SCITXDA, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_QUAL_ASYNC);

    //
    // Initialize SCIA and its FIFO.
    //
    SCI_performSoftwareReset(SCIA_BASE);


    //
    // Configure SCIA for echoback.
    //
    SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 250000, (SCI_CONFIG_WLEN_8 |
                                                        SCI_CONFIG_STOP_ONE |
                                                        SCI_CONFIG_PAR_NONE));
    SCI_resetChannels(SCIA_BASE);
    SCI_resetRxFIFO(SCIA_BASE);
    SCI_resetTxFIFO(SCIA_BASE);
    SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_TXFF | SCI_INT_RXFF);
    SCI_enableFIFO(SCIA_BASE);
    SCI_enableModule(SCIA_BASE);
    SCI_performSoftwareReset(SCIA_BASE);
}

uint8_t i2c_write(uint8_t addr,const uint8_t* data,uint8_t count){
    //wait until the bus is not busy anymore (e.g. STOP condition has been sent)
    while(I2C_getStopConditionStatus(I2CA_BASE))
        ;

    //set the I2C slave address to the write address
    I2C_setSlaveAddress(I2CA_BASE,I2C_W2BW_ADDRESS);
    //set the number of bytes to be sent
    I2C_setDataCount(I2CA_BASE, count);
    //push the data to the I2C TX FIFO
    uint8_t i=0;
    for(i=0; i<count; i++){
        I2C_putData(I2CA_BASE,data[i]);
    }
    //set the I2C mode to master
    I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
    //send the start condition
    I2C_sendStartCondition(I2CA_BASE);
    //send the stop condition
    I2C_sendStopCondition(I2CA_BASE);
    return 0;
}

uint8_t i2c_read(uint8_t addr,uint16_t* data,uint8_t count){
    //wait until the bus is not busy anymore (e.g. STOP condition has been sent)
    while(I2C_getStopConditionStatus(I2CA_BASE))
        ;

    uint8_t i=0;
    //set the I2C slave address to the write address
    I2C_setSlaveAddress(I2CA_BASE,I2C_W2BW_ADDRESS);
    //set the I2C mode to master & repeat mode (data is read until STOP condition)
    I2C_setConfig(I2CA_BASE, I2C_MASTER_RECEIVE_MODE|I2C_REPEAT_MODE);
    //send the start condition
    I2C_sendStartCondition(I2CA_BASE);


    uint8_t bytes_read=0;
    while((count-bytes_read)>16){
        //wait until 16 bytes have been read
        while(I2C_getRxFIFOStatus(I2CA_BASE)!=I2C_FIFO_RX16)
            ;
        //copy the 16 bytes to the data buffer
        for(i=0; i<16; i++)
            data[bytes_read+i]=I2C_getData(I2CA_BASE);
        bytes_read+=16;
    }
    uint8_t remaining_bytes=count-bytes_read;
    //wait for the remaining bytes to be read into the RX FIFO
    while(I2C_getRxFIFOStatus(I2CA_BASE)!=remaining_bytes)
        ;
    I2C_RxFIFOLevel level=I2C_getRxFIFOStatus(I2CA_BASE);
    //send the stop condition
    I2C_sendStopCondition(I2CA_BASE);
    //copy the remaining bytes
    //retreive the latest bit (e.g. the bit that was received most recently)
    //data[remaining_bytes-1]=I2C_getData(I2CA_BASE);
    //copy the remaining received bits from the FIFO
    for(i=0; i<remaining_bytes; i++)
        data[bytes_read+i]=I2C_getData(I2CA_BASE);

    return 0;
}

void parse_akm_meas(const uint8_t* bytes,struct akm_meas* meas){
    //read the status byte
    meas->status=bytes[0];
    //parse Bz value
    uint16_t Bz=0;
    Bz=bytes[1];
    Bz=Bz<<8;
    Bz=Bz|bytes[2];
    //parse By value
    uint16_t By=0;
    By=bytes[3];
    By=By<<8;
    By=By|bytes[4];
    //parse Bx value
    uint16_t Bx=0;
    Bx=bytes[5];
    Bx=Bx<<8;
    Bx=Bx|bytes[6];
    //fill in structure
    meas->Bx=(int16_t)Bx;
    meas->By=(int16_t)By;
    meas->Bz=(int16_t)Bz;
}

//definitions for AKM comm
//----CNTL1 register (16bit)
const uint8_t ADDR_CNTL1=0x20;
const uint8_t CNTL1_LOW_DRDY_EVENT_EN=0b00000001;
// upper 8 bits are all zero for this register
//----CNTL2 register (8bit)
const uint8_t ADDR_CNTL2=0x21;
const uint8_t CNTL2_MEASMODE6=0x0C;     //500Hz continuous measurement mode
const uint8_t CNTL2_SINGLEMEAS=0x01;    //single measurement mode
//----additional addresses
const uint8_t ADDR_STATUS=0x10;
const uint8_t ADDR_STATUS_AND_FIELDS=0x17;

//global variables
struct akm_meas current_meas;

//global memores of last N measurements
#define N_MEM 1024
int16_t Bxmem[N_MEM]={0};
int16_t Bymem[N_MEM]={0};
int16_t Bzmem[N_MEM]={0};

//
// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();
    //
    // Disable pin locks and enable internal pullups.
    //
    Device_initGPIO();
    //
    // Initialize PIE and clear PIE registers. Disable CPU interrupts.
    //
    Interrupt_initModule();
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //init the I2C interface
    pinmux_init();
    gpio_init();
    init_i2c();

    //enable / disable the I2C module
    I2C_disableModule(I2CA_BASE);
    DEVICE_DELAY_US(200000u);
    I2C_enableModule(I2CA_BASE);


    //enable event on data ready (e.g. odint pulled low when data ready)
    const uint8_t WRITE_CONFIG_CNTL1[]={ADDR_CNTL1,CNTL1_LOW_DRDY_EVENT_EN,0x00};
    //set measurement mode to MODE6 (e.g. single measurement mode)
    const uint8_t WRITE_CONFIG_CNTL2[]={ADDR_CNTL2,CNTL2_SINGLEMEAS};
    //write the address to be read to the sensor using I2C write command
    const uint8_t WRITE_STATUS_AND_FIELDS_ADDR[]={ADDR_STATUS_AND_FIELDS};

    //initialize AKM sensor
    i2c_write(0,WRITE_CONFIG_CNTL1,3);
    i2c_write(0,WRITE_CONFIG_CNTL2,2);
    DEVICE_DELAY_US(2000000u);

    /* read status register for debugging purposes, not needed
    uint8_t read_buf[6];
    //first, write the random address to be read to the sensor using a I2C write transaction
    const uint8_t WRITE_RAND_ADDR[]={ADDR_STATUS};
    i2c_write(0,WRITE_RAND_ADDR,1);
    i2c_read(0,read_buf,1);
    */

    //initialize the SCI comm interface to the PC
    sci_comm();

    //set up timer & enable interrupts
    timer_init();
    Interrupt_enableMaster();
    EINT;
    ERTM;

    uint16_t loop_counter=0;
    for(;;){
        if(start_meas){
            //toggle the heartbeat pin
            GPIO_togglePin(HEARTBEAT_PIN);

            //set the mode to single measurement mode via I2C, this triggers a new measurement
            i2c_write(0,WRITE_CONFIG_CNTL2,2);
            //DEVICE_DELAY_US(100u);

            i2c_write(0,WRITE_STATUS_AND_FIELDS_ADDR,1);
            //DEVICE_DELAY_US(100u);

            //read 7 bytes from the address
            // for some reason, with the current `i2c_read` function, we need to read 8 bytes instead of 7. the first byte that is read seems to be random
            i2c_read(0,read_buf,7+1);

            //check whether the sample read was a start of frame sample
            if(GPIO_readPin(SOF_GPIO))
                is_sof=1;
            else
                is_sof=0;

            //parse magnetic data from sensor
            parse_akm_meas(read_buf+1,&current_meas);

            //serialize last measurement and send over UART
            serialize_akm(sendbuf,&current_meas);
            SCI_writeCharArray(SCIA_BASE,sendbuf,sizeof(sendbuf));


            start_meas=0;
            loop_counter+=1;
        }
    }
}

//
// End of File
//
  

I am using this code to send this very simple debug message but the serial monitor receives it incorrectly 

  • Hello,

    If you are using SCI_writeCharArray(), please note that the DriverLib sci.c has a bug here (shown in image below) where the SCI_FIFO_TX15 should be SCI_FIFO_TX16.

    The corrected function should be:

    void
    SCI_writeCharArray(uint32_t base, const uint16_t * const array,
                       uint16_t length)
    {
        //
        // Check the arguments.
        //
        ASSERT(SCI_isBaseValid(base));
    
        uint16_t i;
        //
        // Check if FIFO enhancement is enabled.
        //
        if(SCI_isFIFOEnabled(base))
        {
            //
            // FIFO is enabled.
            // For loop to write (Blocking) 'length' number of characters
            //
            for(i = 0U; i < length; i++)
            {
                //
                // Wait until space is available in the transmit FIFO.
                //
                while(SCI_getTxFIFOStatus(base) == SCI_FIFO_TX15)
                {
                }
    
                //
                // Send a char.
                //
                HWREGH(base + SCI_O_TXBUF) = array[i];
            }
        }
        else
        {
            //
            // FIFO is not enabled.
            // For loop to write (Blocking) 'length' number of characters
            //
            for(i = 0U; i < length; i++)
            {
                //
                // Wait until space is available in the transmit buffer.
                //
                while(!SCI_isSpaceAvailableNonFIFO(base))
                {
                }
    
                //
                // Send a char.
                //
                HWREGH(base + SCI_O_TXBUF) = array[i];
            }
        }
    }

    Please either copy paste this directly into your main .c file or edit your C2000Ware sci.c and rebuild your driverlib.lib and let me know if this changes the behavior you see. If not, I can make further suggestions. Thanks!

    Best Regards,

    Allison