2015-03-13 02:36 AM
Hi,
I am trying to interface to the Heimann 16x16 sensor but having issue with the timings and synchronization. There is only one bi-directional data line as shown in the pinouts below.The device acts as a master spi device when the CONT line is 1 and the data is transmitted continuously. When the CONT line is 0, the device becomes a slave device and release the control of the clock and data line. The code use for setting the the STM32 device to a slave device is shown below.SPI_InitTypeDef spi_init_struct;
NVIC_InitTypeDef nvic_init_struct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_14;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
SPI_StructInit(&spi_init_struct);
spi_init_struct.SPI_Direction = SPI_Direction_1Line_Rx;
spi_init_struct.SPI_Mode = SPI_Mode_Slave;
spi_init_struct.SPI_DataSize = SPI_DataSize_8b;
spi_init_struct.SPI_CPOL = SPI_CPOL_Low;
spi_init_struct.SPI_CPHA = SPI_CPHA_1Edge;
spi_init_struct.SPI_NSS = SPI_NSS_Soft;
spi_init_struct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
spi_init_struct.SPI_FirstBit = SPI_FirstBit_MSB;
spi_init_struct.SPI_CRCPolynomial = 0;
SPI_Init(SPI2, &spi_init_struct);
/* Configure the SPI interrupt priority */
nvic_init_struct.NVIC_IRQChannel = SPI2_IRQn;
nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init_struct.NVIC_IRQChannelSubPriority = 0;
nvic_init_struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init_struct);
/* Enable SPI */
SPI_Cmd(SPI2, ENABLE);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_ERR, ENABLE);
SPI_Cmd(SPI2, ENABLE);
To set the clock for the sensor, the code is shown below.
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
GPIO_InitTypeDef GPIO_InitStruct;
/* Clock for GPIOD */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStruct);
/* Enable clock for TIM4 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_BaseStruct.TIM_Prescaler = 0;
/* Count up */
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
//TIM_BaseStruct.TIM_Period = 83; /* 10kHz PWM */
TIM_BaseStruct.TIM_Period = 63;
/* 10kHz PWM */
//TIM_BaseStruct.TIM_Period = 41; /* 10kHz PWM */
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
/* Initialize TIM4 */
TIM_TimeBaseInit(TIM4, &TIM_BaseStruct);
/* Start count on TIM4 */
TIM_Cmd(TIM4, ENABLE);
TIM_OCInitTypeDef TIM_OCStruct;
/* Common settings */
/* PWM mode 2 = Clear on compare match */
/* PWM mode 1 = Set on compare match */
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
//TIM_OCStruct.TIM_Pulse = 20; /* 50% duty cycle */
//TIM_OCStruct.TIM_Pulse = 43; /* 50% duty cycle */
TIM_OCStruct.TIM_Pulse = 32;
/* 50% duty cycle */
TIM_OC2Init(TIM4, &TIM_OCStruct);
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
The SPI interrupt is shown below. The data is sent to the PC via the USART.
void
SPI2_IRQHandler(
void
)
{
/* SPI in Slave Receiver mode--------------------------------------- */
if
(SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET)
{
newData = SPI_I2S_ReceiveData(SPI2);
Queue_Push(&thermopileQueue, &newData);
}
/* SPI Error interrupt--------------------------------------- */
if
(SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_OVR) == SET)
{
SPI_I2S_ReceiveData(SPI2);
SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_OVR);
}
}
Read Register
The logic analyser capture below shows the address increment.
Can anyone see anything wrong with the code and why the data is not sync?
Paul
2015-03-13 02:40 AM
I have also tried using an gpio interrupt to read the data but still not correct.
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_14;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Tell system that you will use PB10 for EXTI_Line10 */
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource10);
/* PB10 is connected to EXTI_Line10 */
EXTI_InitStruct.EXTI_Line = EXTI_Line10;
/* Enable interrupt */
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
/* Interrupt mode */
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
/* Triggers on rising and falling edge */
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
/* Add to EXTI */
EXTI_Init(&EXTI_InitStruct);
/* Add IRQ vector to NVIC */
/* PB10 is connected to EXTI_Line10, which has EXTI15_10_IRQn vector */
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
/* Set priority */
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
/* Set sub priority */
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
/* Enable interrupt */
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
/* Add to NVIC */
NVIC_Init(&NVIC_InitStruct);
And the interrupt below.
void
EXTI15_10_IRQHandler(
void
)
{
if
(EXTI_GetITStatus(EXTI_Line10) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line10);
if
(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14))
{
newData |= 1 << bitshift;
}
else
{
newData &= ~(1 << bitshift);
}
if
(bitshift == 0)
{
// Add to ring buffer
bitshift = 7;
Queue_Push(&thermopileQueue, &newData);
}
bitshift--;
}
}