I am having an issue configuring my SAM3x8e port to output, when I check the pin with a multimeter I get 1.5V so the pin 0 of Port A just isn't turning on. I believe I configured the port pins to correctly out as outputs but I do not know, I don't have a debugger on me to look at what's happening internally.
#include "sam.h"
uint32_t right_tick = 0;
uint32_t left_tick = 0;
uint32_t LED_status = 1;
void InitializeSystemTimer(void)
{
const uint32_t tickcount = 1000000;
// set value countdown restarts to
SysTick->LOAD = tickcount;
// set interrupt priority
NVIC_SetPriority(SysTick_IRQn, 3);
// restart timer
SysTick->VAL = 0;
// set system tick counter ClockSource/8, creates system tick exception when hits 0, enable system tick count,
SysTick->CTRL = SysTick_CTRL_TICKINT_Msk|SysTick_CTRL_ENABLE_Msk;
}
void InitializeIOPorts(void)
{
// enable Peripheral Clock on Port A
PMC->PMC_PCER0 = ID_PIOA;
// configure output pins
// claim Port A control of pin 0, 1, 2
PIOA->PIO_PER = PIO_PER_P0|PIO_PER_P1|PIO_PER_P2;
// enable Port A output on pins
PIOA->PIO_WPMR = PIO_WPMR_WPKEY_Msk;
// set Port A pin 0, 1, 2 to output
PIOA->PIO_PER = PIO_PER_P0|PIO_PER_P1|PIO_PER_P2;
// set Port A pin 0, 1, 2 to be accessed directly by setting Output Write Enable Register
PIOA->PIO_OWER = PIO_PER_P0|PIO_PER_P1|PIO_PER_P2;
// set Port A pin 0, 1, 2 to high
PIOA->PIO_ODSR = PIO_PER_P0|PIO_PER_P1|PIO_PER_P2;
// configure input pins
// claim Port A control of pin 3, 4
PIOA->PIO_PER = PIO_PER_P3|PIO_PER_P4;
// set pull up resistors on pin 3, 4
PIOA->PIO_PUER = PIO_PER_P3|PIO_PER_P4;
// set interrupt on pin 3, 4
PIOA->PIO_IER = PIO_PER_P3|PIO_PER_P4;
// enable input change interrupt on Pin 3, 4 by setting mask
PIOA->PIO_IMR = PIO_PER_P3|PIO_PER_P4;
// set priority and enable interrupt for port A
NVIC_SetPriority(PIOA_IRQn, 3);
NVIC_EnableIRQ(PIOA_IRQn);
}
void InitializeUart(void)
{
PMC->PMC_PCER0 = ID_UART;
// baud rate is 84Mhz/(16*45)
UART->UART_BRGR = uint32_t(45);
UART->UART_CR = UART_CR_TXEN|UART_CR_RXEN;
NVIC_SetPriority(UART_IRQn,2);
NVIC_EnableIRQ(UART_IRQn);
}
void SysTick_Handler(void)
{
if (LED_status == 0)
{
PIOA->PIO_SODR = PIO_PER_P0;
LED_status = 1;
}
else
{
PIOA->PIO_CODR = PIO_PER_P0;
LED_status = 0;
}
}
void PIOA_Handler(void)
{
uint32_t PORTA_interrupt_status = 0;
PORTA_interrupt_status = PIOA->PIO_ISR;
if ((PORTA_interrupt_status&PIO_PER_P3) == 1)
{
left_tick = left_tick+1;
}
if ((PORTA_interrupt_status&PIO_PER_P4) == 1)
{
right_tick = right_tick + 1;
}
}
void UART_Handler(void)
{
}
int main(void)
{
/* Initialize the SAM system */
SystemInit();
InitializeSystemTimer();
InitializeIOPorts();
/* Replace with your application code */
while (1)
{
}
}
You should double check an example given in the Atmel SAM3X8E Datasheet in the section 31.6 I/O Lines Programming Example.
Have a look at example provided:
Four output signals on I/O lines 4 to 7 (to drive LEDs for example),
driven high and low, no pull-up resistor
and the following configuration:
Register Value to be Written
PIO_PER 0x0000FFFF
PIO_PDR 0xFFFF0000
PIO_OER 0x000000FF
PIO_ODR 0xFFFFFF00
PIO_IFER 0x00000F00
PIO_IFDR 0xFFFFF0FF
PIO_SODR 0x00000000
PIO_CODR 0x0FFFFFFF
PIO_IER 0x0F000F00
PIO_IDR 0xF0FFF0FF
PIO_MDER 0x0000000F
PIO_MDDR 0xFFFFFFF0
PIO_PUDR 0xF0F000F0
PIO_PUER 0x0F0FFF0F
PIO_ABSR 0x00F00000
PIO_OWER 0x0000000F
PIO_OWDR 0x0FFFFFF0
We need the second character from the end (as far as pins 4 to 7 are used in this example) to determine wheather the register should be programmed or not. For instance, "PIO_PER 0x0000FFFF" means the register should be programmed. And, in contrast, "PIO_PDR 0xFFFF0000" means the register should be left untouched.
Thus, the following configuration could is obtained:
PIOA->PIO_PER = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_OER = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_IFDR = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_CODR = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_IDR = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_MDDR = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_PUDR = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
PIOA->PIO_OWDR = PIO_PER_P0 | PIO_PER_P1 | PIO_PER_P2;
I have no SAM3X8E device to check this configuration, but the above considerations may help to find a solution to your problem.
Related
Following #wovano's suggestion, I'll be boiling down the question. For the old versions of the question, see the editing history.
Overview
I'm trying to include I2C on my project (STM32F407ZGT6, MMA8452Q accelerometer) and I'm setting everything bare-metal. I'm using gschorcht library for the accelerometer functions. I currently do not have access to an osciloscope nor to an FT232H.
Problem
I am unsure if my I2C is working properly: when I try to read my Device ID, I get 0x22 instead of 0x2A*. I'm also not being able to read data in a loop. If I use if (mma845x_new_data (sensor) && mma845x_get_float_data (sensor, &data)), I never get a positive condition, and adjusting as below forces me into the Default_Handler: Infinite_Loop for debugging:
void read_data(void)
{
mma845x_float_data_t data;
if (mma845x_new_data (sensor))
{
if(mma845x_get_float_data (sensor, &data))
{
// max. full scale is +-16 g and best resolution is 1 mg, i.e. 5 digits
printf("[MMA845X (xyz)[g]] ax=%+7.3f ay=%+7.3f az=%+7.3f\n", data.ax, data.ay, data.az);
return;
}
}
printf("[not new MMA845X (xyz)[g]] ax=%+7.3f ay=%+7.3f az=%+7.3f\n", data.ax, data.ay, data.az);
}
The Debug tab shows this trace/breakpoint trap thread:
I'm wondering if I did something wrong with my CCR or TRISE setting (I included below the calculations I'm using). I have my SYSCLK at 168MHz and APB1 at 42MHz (APB1PRESC = 4), and I'm currently testing the Standard Mode.
Things I have right
the board has all pull-up resistors properly placed
MODER and AFR are properly set
the SA0 is set to high- or low-logical level to match the device address
STOP is being sent after reading data from DR
Code
void init_gpio(void)
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; //Port B
GPIOB->MODER |= (2U << 12U); //MMA845_SCL || PB6
GPIOB->AFR[0] |= (4U << 24U); //AF4
GPIOB->OTYPER |= (1U << 6U); //Output Type to Open Drain
GPIOB->PUPDR |= (1U << 12U); //Set to Pull-Up
GPIOB->MODER |= (2U << 14U); //MMA845_SDA || PB7
GPIOB->AFR[0] |= (4U << 28U); //AF4
GPIOB->OTYPER |= (1U << 7U); //Output Type to Open Drain
GPIOB->PUPDR |= (1U << 14U); //Set to Pull-Up
}
/*i2c_init*/
void i2c_init(I2C_TypeDef *I2Cx)
{
/*Enable clock access to I2Cs*/
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //enable I2C1
// RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; //enable I2C2
// RCC->APB1ENR |= RCC_APB1ENR_I2C3EN; //enable I2C3
RCC->APB1ENR;
/*Reset I2C*/
I2Cx->CR1 |= I2C_CR1_SWRST; /*!BUSY ON */
I2Cx->CR1 &= ~I2C_CR1_SWRST; /*!BUSY OFF*/
int CCR_VAL;
int TRISE_VAL;
int MAX_FRQ;
/*Set I2C frequency same as APB*/
MAX_FRQ = (SYSCLK/APB1PRESC)/1000000; //= 42 # max clock speed
I2Cx->CR2 &= ~msk(6,0); /*!BUSY ON*/
I2Cx->CR2 |= MAX_FRQ;
if(!MASTER_MODE){
/* Standard Mode = 100kb/s*/
/* CCR calculated by half-period of 100k
* divided by the period of the PCLK
* CCR = ((1/100'000)/2)/(1/42'000'000)
* CCR = 5000ns/~24ns = 210
*/
CCR_VAL = 210;
/* TRISE calculated by PCLK (in MHz) + 1
* TRISE = ((42'000'000/1'000'000) + 1)
* TRISE = 42 + 1 = 43
*/
TRISE_VAL = 43;
}
else
{
/*Fast Mode = 400kb/s*/
if(DUTY_MODE)
{
/*16:9 ratio*/
/* CCR calculated by half-period of 100k
* divided by the sum of the duty ratios
* divided by the period of the PCLK
* t_high = 9 * CCR * TPCLK
* t_low = 16 * CCR * TPCLK
* t_high + t_low = 25 * CCR * TPCLK
* CCR = ((1/400'000)/2) / (25/42'000'000)
* CCR = 1250ns/~595ns = 2.1 ~ 2
*/
CCR_VAL = 2;
}
else
{
//2:1 ratio
/* CCR calculated by half-period of 100k
* divided by the sum of the duty ratios
* divided by the period of the PCLK
* t_high = CCR * TPCLK
* t_low = 2 * CCR * TPCLK
* t_high + t_low = 3 * CCR * TPCLK
* CCR = ((1/400'000)/2) / (3/42'000'000)
* CCR = 1250ns/~71ns = 17.5 ~ 17
*/
CCR_VAL = 17;
}
/* TRISE calculated by PCLK (in MHz) * 0.3ms + 1
* TRISE = ((42'000'000/1'000'000)*(300/1000) + 1)
* TRISE = 42 * 0.3 + 1 = 13.6 ~ 14
*/
TRISE_VAL = 14;
}
/*Set Clock Control value*/
I2Cx->CCR |= CCR_VAL; //assuming APB1 = 42MHz, SM = True
I2Cx->CCR |= (set(DUTY_MODE,I2C_CCR_DUTY_Pos) | set(MASTER_MODE,I2C_CCR_FS_Pos));
I2Cx->TRISE |= TRISE_VAL; //assuming APB1 = 42MHz, SM = True
/*Enable I2C*/
I2Cx->CR1 |= I2C_CR1_PE;
}
void set_addr(I2C_TypeDef *I2Cx, uint8_t sAddr, const uint8_t *mAddr, int read)
{
volatile int temp;
/*Check I2C is not busy*/
while(I2Cx->SR2 & I2C_SR2_BUSY);
/*(1) Generate a START, wait for start flag*/
I2Cx->CR1 |= I2C_CR1_START;
while (!(I2Cx->SR1 & I2C_SR1_SB));
/*Transmit slave address + 'write'*/
I2Cx->DR = sAddr << 1;
/*Wait for the address flag*/
while (!(I2Cx->SR1 & I2C_SR1_ADDR));
temp = I2Cx->SR2; //Clear address flag
/*Send memory address*/
//Make sure TXE is emtpy
while (!(I2Cx->SR1 & I2C_SR1_TXE));
I2Cx->DR = mAddr;
//Wait until transmitter is emtpy
while (!(I2Cx->SR1 & I2C_SR1_TXE));
if(read)
{
/*(2) Generate a START, wait for start flag*/
I2Cx->CR1 |= I2C_CR1_START;
while (!(I2Cx->SR1 & I2C_SR1_SB));
/*Transmit slave address + 'read'*/
I2Cx->DR = (sAddr << 1) | 1;
/*Wait for the address flag*/
while (!(I2Cx->SR1 & I2C_SR1_ADDR));
temp = I2Cx->SR2; //Clear address flag
}
}
int i2c_burst_read(I2C_TypeDef *I2Cx, uint8_t sAddr, const uint8_t *mAddr, uint8_t *string, uint32_t size)
{
if(size == 0)
{
return 0;
}
uint8_t *pData = string; //points at the first byte (char) of string
set_addr(I2Cx, sAddr, mAddr, 1);
/*Enable ACK*/
I2Cx->CR1 |= I2C_CR1_ACK;
while(size > 0U)
{
if(size-- == 1)
{
/*Disable ACK*/
I2Cx->CR1 &= ~I2C_CR1_ACK;
/*Wait until the receive flag is set*/
while(!(I2Cx->SR1 & I2C_SR1_RXNE));
//"Generate STOP" was here before
/*Read data from the DR*/
*pData++ = I2Cx->DR;
break;
}
else
{
/*Wait until the receive flag is set*/
while(!(I2Cx->SR1 & I2C_SR1_RXNE));
/*Read data from the DR*/
*pData++ = I2Cx->DR;
}
}
/*Generate a STOP after receiving*/
I2Cx->CR1 |= I2C_CR1_STOP;
return 1;
}
int i2c_burst_write(I2C_TypeDef *I2Cx, uint8_t sAddr, const uint8_t *mAddr, uint8_t *string, uint32_t size)
{
uint8_t *pData = string; //points at the first byte (char) of string
set_addr(I2Cx, sAddr, mAddr, 0);
while(size > 0U)
{
/*Wait for transmitter to be empty*/
while(!(I2Cx->SR1 & I2C_SR1_TXE));
I2Cx->DR = *pData++;
size--;
}
/*Wait for byte transfer finished flag*/
while(!(I2Cx->SR1 & I2C_SR1_BTF));
/*Generate a STOP after writing*/
I2Cx->CR1 |= I2C_CR1_STOP;
return 1;
}
*This might be due to it being a "different brand". Although it raises some suspicion that it isn't reading all the bits (0x2A in binary is 0b0010 1010 and 0x22 is 0b0010 0010), testing it with another accelerometer gives me the value of 0x05. There's a chance bits are being lost but I'm not sure.
I figured my I2C communication was actually working! So the answer is 'Yes, my CCR and TRISE' settings were correct (at least for the 100kHz mode). To check this, I borrowed an Arduino and I pastade a simple Wire code to read and write from the line. With it, I discovered that:
I could read and write to the I2C bus (without register address)
I had problems when using the register address mAddr
The chip's ID is actually 0x2A
I was mistakenly sending to the function the address of the variable containing the memory address instead of its content (instead of mAddr = 0x1D, I was passing &mAddr as argument).
Also, #wovano guess about the HardFault was correct too. The printf was causing the crash, either because of the floating-point linkage or because it was reading an empty variable (since it wasn't getting any data).
I'm still having issues reading data from the MMA since my STATUS->ZYXDR flag never goes high (mma845x_new_data(sensor) always returns 0). My initialization is as follows, in case anyone has experience with Freescale semiconductors (library link):
#include "mma845x.h"
#define MMA845X_I2C_ADDRESS_1 0x1c // SDO pin is low
#define MMA845X_I2C_ADDRESS_2 0x1d // SDO pin is high
static mma845x_sensor_t* sensor;
void init_MMA_sensor(void)
{
sensor = mma845x_init_sensor(I2C1, MMA845X_I2C_ADDRESS_2);
mma845x_config_int_signals(sensor, mma845x_high_active, mma845x_push_pull);
mma845x_config_hpf(sensor, 0, true);
mma845x_set_scale(sensor, mma845x_scale_2_g);
mma845x_set_mode(sensor, mma845x_high_res, mma845x_odr_50, true, false); //make it active!
}
void read_data(void)
{
mma845x_float_data_t data;
if (mma845x_new_data(sensor))
{
if(mma845x_get_float_data(sensor, &data))
{
// max. full scale is +-16 g and best resolution is 1 mg, i.e. 5 digits
printf("[MMA845X (xyz)[g]] ax=%+7.3f ay=%+7.3f az=%+7.3f\r\n",
data.ax, data.ay, data.az);
return;
}
}
printf("No new data available\r\n");
}
int main(void)
{
/*Setup*/
clock_init_168();
init_systick_MS(SYSTICK_LOAD_VAL_MS);
gpio_init();
uart_init();
i2c_init(I2C1);
init_MMA_sensor();
for(;;)
{
read_data();
delayMS(500);
}
}
But the intial question is resolved. Thanks for all your insight.
I have tried to work with LIS3DSH sensor using SPI protocol. I applied procedures on STM32L0 Discovery kit LoRa. But it didn't work.
My problem is The LIS3DSH x-y-z-axis output value is invalid and the value is not changed. No matter which direction I rotate the device but I check ID of LIS3DSH is correct ( 0011 1111)
Component
STM32L0 Discovery kit LoRa
LIS3DSH (https://www.amazon.com/LIS3DSH-High-Resolution-Three-axis-Accelerometer-Triaxial/dp/B07QS5D9K9/ref=sr_1_4?dchild=1&keywords=LIS3DSH&qid=1615701212&sr=8-4)
init SPI2
...
void HW_SPI2_Init(void)
{
/*##-1- Configure the SPI2 peripheral */
/* Set the SPI parameters */
hspi2.Instance = SPI2;
hspi2.Init.BaudRatePrescaler = SpiFrequency(10000000);
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL = 0
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; // CPHA = 1
// hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA = 0
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
// hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCPolynomial = 10;
SPI2_CLK_ENABLE(); // Enable clock for SPI 2
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the SPI GPIOs */
HW_SPI2_IoInit();
}
...
initialization LIS3DSH
void HW_SPI2_IoInit(void)
{
GPIO_InitTypeDef initStruct = {0};
initStruct.Mode = GPIO_MODE_AF_PP;
initStruct.Pull = GPIO_PULLUP ;
initStruct.Speed = GPIO_SPEED_FAST;
initStruct.Alternate = SPI2_AF;
HW_GPIO_Init(LIS3DH_SCLK_PORT, LIS3DH_SCLK_PIN, &initStruct);
HW_GPIO_Init(LIS3DH_MISO_PORT, LIS3DH_MISO_PIN, &initStruct);
HW_GPIO_Init(LIS3DH_MOSI_PORT, LIS3DH_MOSI_PIN, &initStruct);
initStruct.Mode = GPIO_MODE_OUTPUT_PP;
initStruct.Pull = GPIO_NOPULL;
HW_GPIO_Init(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, &initStruct);
HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 1);
}
CS ON or OFF
void HW_SPI2_CS_ON (void)
{
HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 0);
}
void HW_SPI2_CS_OFF (void)
{
HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 1);
}
Read ID
uint8_t LIS3DSH_DH_CHECK_ID (void)
{
uint8_t addr = LIS3Dx_WHO_AM_I_ADDR | LIS3Dx_READ;
HW_SPI2_CS_ON();
HW_SPI2_SPI_1byte_Write_and_Read(addr);
HW_SPI2_CS_OFF();
UsingTypeint_LIS3DSH_DH.ID = au8BufferRead_SPI2[0];
return UsingTypeint_LIS3DSH_DH.ID;
}
Read X axis ( only) (Incorrect)
void LIS3DSH_DH_GET_XYZ (void)
{
uint8_t addr = LIS3Dx_OUT_X_L_ADDR | LIS3Dx_READ ;
HW_SPI2_CS_ON();
HW_SPI2_SPI_1byte_Write_and_Read(addr);
HW_SPI2_CS_OFF();
addr = LIS3Dx_OUT_X_H_ADDR | LIS3Dx_READ ;
HW_SPI2_CS_ON();
HW_SPI2_SPI_1byte_Write_and_Read(addr);
HW_SPI2_CS_OFF();
}
HW_SPI2_1byte_Write_and_Read
bool HW_SPI2_SPI_1byte_Write_and_Read(uint8_t u8Address)
{
if(HAL_SPI_Transmit(&hspi2, (uint8_t *)&u8Address, 1, HAL_MAX_DELAY) == HAL_OK){
if(HAL_SPI_Receive(&hspi2, (uint8_t *)&au8BufferRead_SPI2[0], 1, HAL_MAX_DELAY) == HAL_OK){
return true;
}
}
return false;
}
Signal
output X L
output X H
Am not sure if you are using the state machine and register accesses of the LIS3DSH accurately.
As a reference see the register mapping in https://github.com/STMicroelectronics/stm32-lis3dsh/blob/main/lis3dsh.h (start at line 95) and the code in https://github.com/STMicroelectronics/stm32-lis3dsh/blob/main/lis3dsh.c
The function that actually writes and reads the SPI bus is void ACCELERO_IO_Write(uint8_t *pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) and void ACCELERO_IO_Read(uint8_t *pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)
This is defined in https://documentation.help/STM32F4-Discovery-BSP/stm32f4__discovery_8c_source.html at lines 560 and 594
In void ACCELERO_IO_Write(uint8_t *pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) the actual SPI write is done at lines 574 to 582
00574 SPIx_WriteRead(WriteAddr);
00577 while(NumByteToWrite >= 0x01)
00578 {
00579 SPIx_WriteRead(*pBuffer);
00580 NumByteToWrite--;
00581 pBuffer++;
00582 }
(as always with SPI first activate register, then write data...)
In SPIx_WriteRead(WriteAddr); the WriteAddr is taken from the register mapping in https://github.com/STMicroelectronics/stm32-lis3dsh/blob/main/lis3dsh.h, start at line 9
(the above code by STM for the LIS3DSH is nice work, this implementation is very clean and structured)
The datasheet of the LIS3DSH is in https://www.st.com/resource/en/datasheet/lis3dsh.pdf, the reference manual is far more detailed it is in https://www.st.com/resource/en/application_note/dm00026768-lis3dsh-3axis-digital-output-accelerometer-stmicroelectronics.pdf it also includes explanation of the state machines, that have to be configured before the device works
I've attached an image showing my oscilloscope readout which is from the code below. Context: I have a Pi and a PIC which need to communicate through UART connection. I've implemented my own flow control which can be seen in the image attached [RTS = Yellow Trace, CTS = Blue Trace, Rx = Green Trace]. The code runs through and is caught in the final switch case statement which turns on an LED. But when i debug the code, no values (well the only value which is read is zero) are read in. At first i thought that i'd configured my PIC clock wrong (which is used to derive the baud rate), but i don't think this is the case. Second i through the FIFO buffer was full of zeros only and considering that i'm sending only four packets of information to the PIC, and my FIFO is 4 registers deep that this was the reason why non of the information was appearing. So i executed a code which removes the dummy bytes but this did not work.
All that is received:
0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0> etc
I got the right settings selected: baud rate: 9600 data bits: 8 parity: none stop bits: 1
If anyone is willing to spend some time looking at my code, can you see any obvious errors?
https://i.stack.imgur.com/aQoAL.jpg
Minimum Reproducible Example
# include <xc.h>
# include <math.h>
# include <stdio.h>
# include <stdio.h>
//Configuration Bits
#pragma config FNOSC = FRCPLL // Internal Fast RC Oscillator (8MHz)
#pragma config FPLLIDIV = DIV_2 // Divide FRC before PLL (Now 4MHz)
#pragma config FPLLMUL = MUL_20 // PLL Multiply (Now 80MHz)
#pragma config FPLLODIV = DIV_2 // Divide After PLL (Now 40MHz)
#pragma config FPBDIV = DIV_1 // Pheripheral Bus Clock (At 40KHz)
#pragma config FWDTEN = OFF // Watchdog Timer Disabled
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
#pragma config JTAGEN = OFF // Disable JTAG
#pragma config FSOSCEN = OFF // Disable Secondary Oscillator
//*****************************UART Functions***********************************
void UART_Config (void) // Baude Rate of 9600, 8-Bit Data , 1 Stop Bit
{
U1MODEbits.BRGH = 0;
U1BRG = 259; //U1BRG = (40M/ (16 * 9.6k))) - 1
U1MODEbits.SIDL = 0; // Continue operation in SLEEP mode
U1MODEbits.IREN = 0; // IrDA is disabled
U1MODEbits.RTSMD = 0; // U1RTS pin is in Flow Control mode
U1MODEbits.UEN = 0b00; // U1TX, U1RX are enabled
U1MODEbits.WAKE = 1; // Wake-up enabled
U1MODEbits.LPBACK = 0; // Loopback mode is disabled
U1MODEbits.RXINV = 0; // U1RX IDLE state is '1'
U1MODEbits.PDSEL = 0b00; // 8-bit data, no parity
U1MODEbits.STSEL = 0; // 1 stop bit
U1STAbits.UTXINV = 0; // U1TX IDLE state is '1'
U1MODEbits.ON = 1; // UART1 is enabled
U1STAbits.URXEN = 1; // UART1 receiver is enabled
U1STAbits.UTXEN = 1; // UART1 transmitter is enabled
}
void Send_UART_Data(unsigned int c) // PIC Sending Data for Pi to Read
{
U1STAbits.UTXEN = 1; // Make sure transmitter is enabled
// while(CTS) // Optional CTS (Clear to Send) use
while(U1STAbits.UTXBF); // Wait while buffer is full
U1TXREG = c; // Transmit character
}
int Read_UART_Data (void) // PIC Reading Sent Data from Pi
{
int c;
while(!U1STAbits.URXDA) // Wait for information to be received
c = (int)U1RXREG; // Convert Character to Value
return c;
}
ADC_To_UART (unsigned int ADC)
{
unsigned int temp_A = 0x00;
unsigned int temp_B = 0x00;
// Splitting a 10 Bit Word Into 2 Bytes [aa aaaa aabb]
// Start Bit = 1 , Stop Bit = 0
// UART Transmission Pattern [1 aaaa aaaa 0 0000 00 bb]
temp_A = ADC >> 2; // MSB(8 Bits) ~ ADC[9:2] [aaaa aaaa]
temp_B = ADC & 0x003; // LSB(2 Bits) ~ ADC[1:0] [0000 00bb]
Send_UART_Data(temp_A);
Send_UART_Data(temp_B);
}
[enter image description here][1]
//*********************Enumerated Variable Declaration**************************
//Program Flow Control
enum Comm_State {Phase1A, Phase1B, Phase1C, Phase1D, Phase1E, Phase2A, Phase2B, Phase2C, Phase2D, Phase2E, Phase2F, Phase2G};
//******************************************************************************
//********************************MAIN******************************************
int main( )
{
//***************************Configuration**********************************
// I/O Definitions
#define UART_TRIS_RX TRISBbits.TRISB13 // UART RX - Reciever Pin (PPS)
#define UART_TRIS_TX TRISBbits.TRISB15 // UART TX - Transmission Pin (PPS)
#define UART_TRIS_CTS_PIC TRISAbits.TRISA4 // UART CTS_1 - Clear to Send - Output [CTS PIC]
#define UART_TRIS_RTS_PIC TRISBbits.TRISB4 // UART RTS_1 - Ready to Send - Output [RTS PIC]
#define UART_TRIS_CTS_PI TRISAbits.TRISA3 // UART CTS_2 - Clear to Send - Input [CTS PI]
#define UART_TRIS_RTS_PI TRISAbits.TRISA2 // UART_RTS_2 - Ready to Send - Input [RTS PI]
#define SPI_TRIS_SCK TRISBbits.TRISB14 // SPI SCK - Serial Clock Pin (PPS?)
#define SPI_TRIS_SDO TRISBbits.TRISB6 // SPI SDO - Serial Data Out Pin (PPS?)
#define SPI_TRIS_CS_1 TRISBbits.TRISB8 // SPI CS1 - DAC 2 Chip Select Pin (PPS?)
#define SPI_TRIS_CS_2 TRISBbits.TRISB7 // SPI CS2 - DAC 1 Chip Select Pin (PPS?)
#define AN4_TRIS TRISBbits.TRISB2 // Analogue Read 3
#define AN3_TRIS TRISBbits.TRISB1 // Analogue Read 2
#define AN2_TRIS TRISBbits.TRISB0 // Analogue Read 1
#define V_REF_TRIS_Plus TRISAbits.TRISA0 // Analogue V_REF(+) (Forms VRange)
#define V_REF_TRIS_Minus TRISAbits.TRISA1 // Analogue V_REF(-) (Forms VRange)
#define Reg_Enable_TRIS_D TRISBbits.TRISB9 // Regulator Digital Control (Output)
#define Reg_Enable_TRIS_M TRISBbits.TRISB12 // Regulator Button (Input)
// Port Input/Output Configuration [TRISB]
TRISB = 0x1004; // All of PortB set as Outputs Except for RB12 (Reg Enable) and RB2 (Input -> Analogue Input (Voltage)) (Port B) = (0000 ... 0100)
TRISA = 0x0003; // Set up A0 [Pin 2] and A1 [Pin 3] as V_REF(+) and V_REF(-) Respectively (Port B) = (0000 ... 0011)
UART_TRIS_RX = 1; // UART Receiver ~ Input
UART_TRIS_TX = 0; // UART Transmission ~ Output
UART_TRIS_CTS_PIC = 0; // UART "CTS_PIC" ~ Output
UART_TRIS_RTS_PIC = 0; // UART "RTS_PIC" ~ Output
UART_TRIS_CTS_PI = 1; // UART "CTS_PI" ~ Input
UART_TRIS_RTS_PI = 1; // UART "RTS_PI" ~ Input
SPI_TRIS_SCK = 0; // SPI Clock ~ Output
SPI_TRIS_SDO = 0; // SPI Data Output ~ Output
SPI_TRIS_CS_1 = 0; // SPI Chip Select 1 ~ Output
SPI_TRIS_CS_2 = 0; // SPI Chip Select 2 ~ Output
AN4_TRIS = 1; // Analogue Read In ~ Input
AN3_TRIS = 1; // Analogue Read In ~ Input
AN2_TRIS = 1; // Analogue Read In ~ Input
V_REF_TRIS_Plus = 1; // V_Ref(+) ~ Input
V_REF_TRIS_Minus = 1; // V_Ref(-) Differential Measurements ~ Input
Reg_Enable_TRIS_D = 0; // Regulator Digital Control (Output)
Reg_Enable_TRIS_M = 1; // Regulator Switch Control (Input)
// Peripheral Pin Select Configurations
U1RXR = 0x0011; // UART PPS Mapping
RPB15R = 0x0001; // UART PPS Mapping
// Analogue Pin Configurations
ANSELB = 0x0028; // RB0 RB1 RB2 = AN2 AN3 AN4 [0001 1100]
ANSELA = 0x0000; // Set all Analogue Inputs of Port A Off
//**************Sub-System Configurations*********************************//
// UART Control Configure
UART_Config(); //UART Control Configure
#define PIC_CTS LATAbits.LATA4 // Output Set Definition [1]
#define PIC_RTS LATBbits.LATB4 // Output Set Definition [2]
#define PI_CTS PORTAbits.RA3 // Input Read Definition [2]
#define PI_RTS PORTAbits.RA2 // Input Read Definition [1]
// Analogue Control Configure
ADC_Config(); // Configure ADC
AD1CON1SET = 0x8000; // Enable ADC
//***************Variable Declarations************************************//
enum Comm_State Communication_State = Phase1A; //Controller Variable
unsigned int temp1 = 0;
unsigned int Comms_Flag_1 = 0;
unsigned int ConFlag = 1;
unsigned int i = 1;
unsigned int UART_ADC_CV_1 = 0;
unsigned int UART_ADC_CV_2 = 0;
unsigned int ADC_CV = 0;
unsigned int UART_ADC_CC_1 = 0;
unsigned int UART_ADC_CC_2 = 0;
unsigned int ADC_CC = 0;
unsigned int DAC_CV = 0;
float I_CC = 0;
float V_CV = 0;
//***************Program Flow - Switch State Controlled*******************//
while(1)
{
switch (Communication_State)
{
case Phase1A: // Check For Pi Ready to Send CV ADC Value
//PIC_CTS = 0;
//Pic_Refresh();
PIC_RTS = 0;
PIC_CTS = 1;
if (PI_RTS == 1)
{
PIC_CTS = 0;
Communication_State = Phase1B;
}
break;
case Phase1B: // Receive CV ~ 12 Bit ADC Value [Two Data Packets with 0.01 Second Delay]
ConFlag = 1;
i = 1;
while (ConFlag == 1)
{
if (PI_RTS == 1 && i == 1)
{
UART_ADC_CV_1 = Read_UART_Data(); //Data Packet 1 Returned - MSB(Bit 15) to Bit 8
i++;
}
else if (PI_RTS == 1 && i == 2)
{
UART_ADC_CV_2 = Read_UART_Data(); //Data Packet 2 Returned - Bit (7)) to LSB(Bit 0)
}
else
{
ConFlag = 0;
}
}
Communication_State = Phase1C;
break;
case Phase1C: // Check for CC Value
delay(); //Ensure that Pi_RTS has gone low after sending last Transmission (Prevents Code from Running Away)
PIC_CTS = 1;
if (PI_RTS == 1)
{
PIC_CTS = 0;
Communication_State = Phase1D;
}
break;
case Phase1D: // Receive CC Value [Two Data Packets with 0.01 Second Delay]
ConFlag = 1;
i = 1;
while (ConFlag == 1)
{
if (PI_RTS == 1 && i == 1)
{
UART_ADC_CC_1 = Read_UART_Data(); //Data Packet 1 Returned - MSB(Bit 15) to Bit 8
i++;
}
else if (PI_RTS == 1 && i == 2)
{
UART_ADC_CC_2 = Read_UART_Data(); //Data Packet 2 Returned - Bit (7)) to LSB(Bit 0)
}
else
{
ConFlag = 0;
}
}
Communication_State = Phase1E;
break;
case Phase1E: // Calculations
// CV Calculations
temp1 = UART_ADC_CV_1 << 8;
ADC_CV = temp1 + UART_ADC_CV_2;
V_CV = ADC_CV * (4.096/4096);
DAC_CV = ADC_CV | 4096;
Comms_Flag_1 = SPI_Transfer(DAC_CV ,1); // Data Transmitted to DAC 1, Upon Transmission LED Turns Green (No Acknowledgement)
// CC Calculations
temp1 = UART_ADC_CC_1 << 8;
ADC_CC = temp1 + UART_ADC_CC_2;
I_CC = ADC_CC * (4.096/4096);
Communication_State = Phase2A;
break;
case Phase2A:
while(1)
{
LATBbits.LATB5 = 1;
}
break;
}
}
return 1;
}
In Read_UART_Data, you have:
while(!U1STAbits.URXDA)
c = (int)U1RXREG;
I think you're missing a semicolon because this is actually:
while (!U1STAbits.URXDA)
c = (int) U1RXREG;
This means that c is set only when the UART receiver is not ready.
What I think you meant is:
while (!U1STAbits.URXDA);
c = (int) U1RXREG;
I'm trying to read information from an MPU6050 sensor using the SAM4S-EK2 dev board, with an ATSAM4SD32C microcontroler, showing the data in the on-board LCD display. However, when I try to read the data, the received value that shows up in the LCD is always the same.
What am I doing wrong?
I'm using Atmel Studio 7 with ASF version 3.32.0
Here is my current code:
#include <asf.h>
#define TWI_CLK 200000
#define ADDRESS 0x68
#define READ 0x3b
#define ILI93XX_LCD_CS 1
twi_options_t opt;
struct ili93xx_opt_t g_ili93xx_display_opt;
void configure_lcd()
{
/** Enable peripheral clock */
pmc_enable_periph_clk(ID_SMC);
/** Configure SMC interface for Lcd */
smc_set_setup_timing(SMC, ILI93XX_LCD_CS, SMC_SETUP_NWE_SETUP(2)
| SMC_SETUP_NCS_WR_SETUP(2)
| SMC_SETUP_NRD_SETUP(2)
| SMC_SETUP_NCS_RD_SETUP(2));
smc_set_pulse_timing(SMC, ILI93XX_LCD_CS, SMC_PULSE_NWE_PULSE(4)
| SMC_PULSE_NCS_WR_PULSE(4)
| SMC_PULSE_NRD_PULSE(10)
| SMC_PULSE_NCS_RD_PULSE(10));
smc_set_cycle_timing(SMC, ILI93XX_LCD_CS, SMC_CYCLE_NWE_CYCLE(10)
| SMC_CYCLE_NRD_CYCLE(22));
smc_set_mode(SMC, ILI93XX_LCD_CS, SMC_MODE_READ_MODE
| SMC_MODE_WRITE_MODE);
/** Initialize display parameter */
g_ili93xx_display_opt.ul_width = ILI93XX_LCD_WIDTH;
g_ili93xx_display_opt.ul_height = ILI93XX_LCD_HEIGHT;
g_ili93xx_display_opt.foreground_color = COLOR_BLACK;
g_ili93xx_display_opt.background_color = COLOR_WHITE;
/** Switch off backlight */
aat31xx_disable_backlight();
/** Initialize LCD */
ili93xx_init(&g_ili93xx_display_opt);
/** Set backlight level */
aat31xx_set_backlight(AAT31XX_AVG_BACKLIGHT_LEVEL);
ili93xx_set_foreground_color(COLOR_WHITE);
ili93xx_draw_filled_rectangle(0, 0, ILI93XX_LCD_WIDTH,
ILI93XX_LCD_HEIGHT);
/** Turn on LCD */
ili93xx_display_on();
ili93xx_set_cursor_position(0, 0);
}
int main (void)
{
sysclk_init();
board_init();
configure_lcd();
pio_configure(PIOB, PIO_PERIPH_B, (PIO_PB5A_TWCK1 | PIO_PB4A_TWD1), PIO_OPENDRAIN);
pmc_enable_periph_clk(ID_TWI1);
opt.master_clk = sysclk_get_peripheral_hz();
opt.speed = TWI_CLK;
twi_enable_master_mode(TWI1);
twi_master_init(TWI1, &opt);
twi_packet_t packet;
uint8_t answer[20];
answer[0]=0x00;
//pacote.addr[0] = 0x6b;
//pacote.addr_length = 1;
//pacote.buffer = &resposta;
//pacote.chip = ENDERECO_SENSOR;
//pacote.length = 1;
//
//if(twi_master_write(TWI1, &pacote) == TWI_SUCCESS)
//{
//ili93xx_set_foreground_color(COLOR_WHITE);
//ili93xx_draw_filled_rectangle(0, 0, 200, 200);
//ili93xx_set_foreground_color(COLOR_BLACK);
//ili93xx_draw_string(0, 0, "Enviou");
//}
while(1)
{
packet.addr[0] = READ;
packet.addr_length = 1;
packet.buffer = &answer;
packet.chip = ADDRESS;
packet.length = 14;
twi_master_read(TWI1, &packet);
char a[20];
int16_t b;
b = (answer[2] << 8 | answer[3]);
sprintf(a,"%i",b);
ili93xx_set_foreground_color(COLOR_WHITE);
ili93xx_draw_filled_rectangle(95, 175, 240, 200);
ili93xx_set_foreground_color(COLOR_BLACK);
ili93xx_draw_string(100, 180, a);
delay_ms(100);
}
}
#include <ti/sysbios/family/arm/cc26xx/Power.h>
#include <ti/sysbios/family/arm/cc26xx/PowerCC2650.h>
#include <driverLib/timer.h>
Task_Struct taskStruct;
void taskFxn(UArg a0, UArg a1);
PIN_init(BoardGpioInitTable);
Task_Params params;
Task_Params_init(¶ms);
params.priority = TASK_PRI;
params.stackSize = TASK_STACK_SIZE;
params.stack = taskStack;
Task_construct(&taskStruct, taskFxn, ¶ms, NULL);
BIOS_start();
bool timerEnabled = 0;
PIN_Config pwmExamplePins[] = {
Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_KEY_SELECT | PIN_INPUT_EN | PIN_HYSTERESIS | PIN_HYSTERESIS | PIN_PULLUP | PIN_IRQ_NEGEDGE,
PIN_TERMINATE };
PIN_State pinState;
PIN_Handle pinHandle;
static void timerInitialize() {
TimerConfigure(GPT0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);
TimerLoadSet(GPT0_BASE, TIMER_A, TIMER_LOADSET);
TimerMatchSet(GPT0_BASE, TIMER_A, TIMER_MATCH);
//Stall timer when halting debugger
//TimerStallControl(GPT0_BASE, TIMER_A, true)
}
static void pinCallBack(PIN_Handle handle, PIN_Id pinId) {
if( timerEnabled) {
timerEnabled = 0;
// Allow standby in TI RTOS and stop timer
Power_releaseConstraint(Power_SB_DISALLOW);
TimerDisable(GPT0_BASE, TIMER_A);
}
else {
timerEnabled = 1;
// Disallow standby in TI RTOS to allow timer to run
Power_setConstraint(Power_SB_DISALLOW);
TimerEnable(GPT0_BASE, TIMER_A);
}
void taskFxn(UArg a0, UArg a1) {
// Register client for pins in pwmExamplePins array
pinHandle = PIN_open(&pinState, pwmExamplePins);
// Route LED1 pin on SmartRF06EB to IO event port 0 (0 = Timer0A, 1 = Timer0B, 2 = Timer1A..)
PINCC26XX_setMux(pinHandle, PIN_ID(Board_LED1), IOC_PORT_MCU_PORT_EVENT0);
PIN_registerIntCb(pinHandle, pinCallBack);
// Turn on PERIPH power domain and clock for GPT0
Power_setDependency(PERIPH_GPT0);
timerInitialize();
// 100ms
uint32_t sleepTicks = 100 * 1000/Clock_tickPeriod;
bool ledValue = 0;
while(1) {
// Let task sleep, chip will go into IDLE or STANDBY mode depending on whether timer is enabled
Task_sleep(sleepTicks);
PIN_setOutputValue(pinHandle, PIN_ID(Board_LED2), ledValue);
// Invert LED value
ledValue = (ledValue ? 0 : 1);
}
Trying to make buzzer work for the CC2650STK SensorTag Texas Instruments device from an example, but it keeps giving the same error and not able to continue further.
fatal error #1965: cannot open source file
"ti/sysbios/family/arm/cc26xx/Power.h"
Is there some file missing from the device itself or should something be downloaded as an extra to continue?
Thank you for your help.