Am trying to read the chip_id of the BMP280 Pressure/Tempeture sensor using the Tiva TM4C123G Launchpad thought the SPI communication protocol.
To begin with let me provide some back ground info and technical details.
Inventory:
- Tiva TM4C123G Launchpad.Datasheet
- BMP280 Digital Pressure Sensor. Datasheet
- Female-to-Male Jumper Wire Dupont Cable x6.
- Breadboard
- IAR Embedded Workbench
To communicate with the sensor the Tiva Launchpad will behave as a Master:
GPIO Port D will be used for Serial Peripheral Interface (SPI)
- PD3(Tx), PD2(Rx) & PD0(Clk)
GPIO Port F will work as our Sleve Slect (Chip Select) signal
- PF2(SS- Slave Select)
Pin Configuration:
TM4C123G | BMP280 |
---|---|
+3.3V | VCC |
GND | GND |
PD0 | SCL |
PD3 | SDA |
PF2 | CSB |
PD2 | SD0 |
CODE
/*-------------LIBRARIES-------------*/
#include <TM4C123GH6PM.h>
#include "stdio.h"
/*---------FUNCTION PROTOTYPES---------*/
void init_SSI1(void); //SSI Module 1 Initialization Function
void delay_ms(uint32_t period_ms); //Time Delay Function
void cs_low(uint8_t dev_id);
void cs_high(uint8_t dev_id);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr);
int main()
{
int8_t rslt;
init_SSI1(); /* Tiva SSI Module 1 Initialization and Configuration call*/
rslt = spi_reg_read(0x00, 0xD0); // Reads the chip-id data from the sensor
return 0;
}
void init_SSI1(void)
{
SYSCTL->RCGCSSI |= 2; /* Enable clock to SSI1 */
SYSCTL->RCGCGPIO |= 8; /* Enable clock to GPIOD for PD3(Tx), PD2(Rx) & PD0(Clk) */
SYSCTL->RCGCGPIO |= 0x20; /* Enable clock to GPIOF for PF3 (- SSslave select) */
/* Configure PD3(Tx), PD2(Rx) & PD0(Clk) as ALT function for SSI1 */
GPIOD->AMSEL &= ~0x0D; /* Disable analog for this pins */
GPIOD->AFSEL |= 0x0D; /* Enable Alternative Function */
GPIOD->PCTL &= ~0x0000FF0F; /* assign pins to SSI1 */
GPIOD->PCTL |= 0x00002202; /* assign pins to SSI1 */
GPIOD->DEN |= 0x0D; /* And make them digital */
/* Configure PORTF 2 for slave select */
GPIOF->DIR |= 0x04; // Make the pin output
GPIOF->DEN |= 0x04; // Make the pin digital
GPIOF->DATA |= 0x04; // Keep SS idle high
/* SPI Master, POL = 0, PHA = 0, Clock = 8 MHz, 16 bit data */
SSI1->CR1 = 0; /* disable SSI and make it master */
SSI1->CC = 0; /* use system clock */
SSI1->CPSR = 2; /* prescaler divided by 2 */
SSI1->CR0 = 0x0007; /* 8 MHz SSI clock, SPI mode, 8 bit data */
SSI1->CR1 |= 2; /* enable SSI1 */
}
void delay_ms(uint32_t period_ms)
{
/* Implement the delay routine according to the target machine */
/* milliseconds delay using one-shot mode*/
SYSCTL->RCGCTIMER |= 1; //enable clock to Timer Block0
TIMER0->CTL = 0; //disable Timer before initialization
TIMER0->CFG = 0X04; //16-bit option
TIMER0->TAMR = 0X01; //one-shot mode and down-counter
TIMER0->TAILR = 16000 * period_ms - 1;//Timer A interval load value register
TIMER0->ICR = 0X1; //clear the TimerA timeout flag.
TIMER0->CTL = 0X01; //enable Timer A after initialization
while ((TIMER0->RIS & 0x1) == 0) { //wait for TimerA timeout flag to set
}
}
void cs_low(uint8_t dev_id)
{
if (dev_id == 0)
{
GPIOF->DATA &= ~0x04; /* Assert SS low */
}
else if (dev_id == 1)
{
GPIOF->DATA |= 0x04; /* keep SS idle high */
}
}
void cs_high(uint8_t dev_id)
{
if (dev_id == 0)
{
GPIOF->DATA |= 0x04; /* keep SS idle high */
}
else if (dev_id == 1)
{
GPIOF->DATA &= ~0x04; /* Assert SS low */
}
}
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr)
{
int8_t rslt;
uint8_t data;
/*
* The parameter dev_id can be used as a variable to select which Chip Select pin has
* to be set low to activate the relevant device on the SPI bus
*/
/*
* Data on the bus should be like
* |----------------+---------------------+-------------|
* | MOSI | MISO | Chip Select |
* |----------------+---------------------|-------------|
* | (don't care) | (don't care) | HIGH |
* | (reg_addr) | (don't care) | LOW |
* | (don't care) | (reg_data[0]) | LOW |
* | (....) | (....) | LOW |
* | (don't care) | (reg_data[len - 1]) | LOW |
* | (don't care) | (don't care) | HIGH |
* |----------------+---------------------|-------------|
*/
cs_low(cs);
while ((SSI1->SR & 0x02) == 0); /* wait until FIFO not full */
SSI1->DR = 0xD0; /* Read Command */
while ((SSI1->SR & 0x02) == 0); /* wait until FIFO not full */
while ((SSI1->SR & 0x04) == 0); /* wait until FIFO not Empty */
data = SSI1->DR; /* read the received byte */
while(SSI1->SR & 0x10); /* wait until SSI is idle (transmit complete) */
cs_high(cs);
return rslt;
}
Additional Resources
Tiva TM4C123G Launchpad Datasheet
BMP280 Digital Pressure Sensor Datasheet
The BPM280 datasheet has the following instructions for reading (p. 31):
The chip_id reg addr is 0xD0
(Take a look to p.24). I will understand that control byte will remain the same: 0xD0
. I'm unable to obtain 0x58
from the sensor, as specify by the BMP280 datasheet. I will appreciate if anyone can provide me any help. In specific an eye on the spi_reg_read
function.