I was able to use the code below to init the SPI and read the values from accelerometer
SPI_InitTypeDef SPI_InitTypeDefStruct;
GPIO_InitTypeDef GPIO_InitTypeDefStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE , ENABLE);
SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //seems like it was here causing trouble
SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI1, &SPI_InitTypeDefStruct);
GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_6;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);
GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOE, &GPIO_InitTypeDefStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
SPI_Cmd(SPI1, ENABLE);
SPI_send(0x23, 0xc9); // resetting the accelerometer internal circuit
//SPI_send(0x20, 0x67); // 100Hz data update rate, block data update disable, x/y/z enabled
SPI_send(0x20, 0x97);
//SPI_send(0x24, 0x20); // Anti aliasing filter bandwidth 800Hz, 16G (very sensitive), no self-test, 4-wire interface
SPI_send(0x24, 0x00); // Anti aliasing filter bandwidth 800Hz, 2G ( sensitive ??), no self-test, 4-wire interface
SPI_send(0x10, 0x00); // Output(X) = Measurement(X) - OFFSET(X) * 32;
SPI_send(0x11, 0x00); // Output(Y) = Measurement(Y) - OFFSET(Y) * 32;
SPI_send(0x12, 0x00); // Output(Z) = Measurement(Z) - OFFSET(Z) * 32;
void SPI_send(uint8_t address, uint8_t data)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, data);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
}
uint8_t SPI_read(uint8_t address)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
address = 0x80 | address; // 0b10 - reading and clearing status
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 0x00);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
return SPI_I2S_ReceiveData(SPI1);
}
Then I combined these code with my project which has an 500Hz interrupt.
It always work at first but if i unplug the board then plug it in again, SPI will only read zeros, even though the LIS3DSH still have readings(i used oscilloscope checked it). I had to download the shorter version of the project code( taking out most of the code in the interrupt) to get SPI to work properly again.
I am using the Kickstart, size-limited IAR ewarm I thought it was because my code exceed the limit. But I did not get warning and my code was not more than 32kb.
I am just confused since it works until I unplug it. Could someone give me some suggestions?
Thanks
I decided just to add the SPI_DeInit(...) before SPI_Init(...). This seems to solve the problem. I still dont understand why it wont reset itself though.
Related
I currently use standard peripheral library to write a driver that enable memory to USART6_TX DMA transfer on a STM32 F407 ZGT6 chip. However, I tried for a long time but the initialization keeps on failing: DMA_GetCmdStatus always returns DISABLE. By using GDB, I found that after the DMA_Init try to write configuration into DMA register, DMA CR register remains 0. The DMA initialize code and execution are as follow:
void DMA_USART6_Init(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size){
DMA_Buffer_Size_GV = DMA_Buffer_Size;
DMA_Start_Pos_GV = DMA_Start_Pos;
/*RCC config*/
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*DMA init*/
//DMA_DeInit(DMA2_Stream7);
DMA_Cmd(DMA2_Stream7, DISABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)){}
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_Channel = DMA_Channel_5;
DMA_InitStruct.DMA_PeripheralBaseAddr = USART6_BASE + 0x04;//(uint32_t)&USART6->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t) dubuff;//(uint32_t) DMA_Start_Pos;
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_BufferSize = (uint16_t)sizeof(dubuff);//DMA_Buffer_Size;
printf("buffer size should be %d \r\n", (uint16_t)sizeof(dubuff));
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
printf("data counter after init %d \r\n", DMA_GetCurrDataCounter(DMA2_Stream7));
}
for the ENABLE code
void DMA_USART6_Enable_DMA(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size, int MB){
Max_Buffer = MB;
USART6_init_for_DMA();
DMA_USART6_Init(DMA_Start_Pos, DMA_Buffer_Size);
DMA_USART6_NVIC_Init();
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Stream7, ENABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == DISABLE)){}//program stucked in this loop
}
for the USART6 code:
void USART6_init_for_DMA(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 57600;//115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}
and the GDB result:
the value that should be written into DMA CR register
text in the picture 1:
367 DMAy_Streamx->CR = tmpreg;
(gdb) print tmpreg
$7 = 167904576
the DMA CR register remains 0
text in the picture2:
371 tmpreg = DMAy_Streamx->FCR;
(gdb) print *DMAy_Streamx
$10 = {CR = 0, NDTR = 0, PAR = 0, M0AR = 0, M1AR = 0, FCR = 0}
Please tell me if there is anything I can provide about my problem or things I can try further...
Note: In the same program, my USART6 and GPIO works fine.
When the desired stream is activated, the relevant registers can no longer be configured. Only in dual buffer mode can memory addresses 0 and 1 be updated according to the bit CT function. You must first deactivate the relevant channel and then apply the changes.
I am OP.
At the start, I have a feeling that it could be an obvious mistake and that's true.
It turns out that I should use RCC_AHB1PeriphClockCmd instead of RCC_AHB1PeriphResetCmd because OBVIOUSLY the later accessed RSTR (RCC Reset register) rather than ENR an thus clock is not enable (about that Codo is right).
Well, Hope guys whoever sees this question won't repeat this embarrass mistake ;(
I have a weight cell which replies to specific frames over RS485 (cell contains its own communication protocol). Manufacturer has a software to test the cell so I connect it to my pc using a RS485 to USB converter and I am able to connect to the cell and send/receive frames. Here are the parameters I use and you can see TX-RX frames below:
Now I want to manage this protocol with a STM32 board but I am not receiving frames properly. I am using NUCLEO-F401RE and RS485 CAN Shield from Waveshare (https://www.waveshare.com/wiki/RS485_CAN_Shield). Here is what I do and my UART configuration:
Main program
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
MX_USART1_UART_Init();
MX_USART2_UART_Init();
printf("NUCLEOF401RE - RS485 RX\r\n");
while (1)
{
// Activate sending status
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1);
txBuffer[0] = 0x44; // SOF
txBuffer[1] = 0x01; // DIR
txBuffer[2] = 0x00; // ERR
txBuffer[3] = 0x25; // CMD
txBuffer[4] = 0x00; // DATOS0
txBuffer[5] = 0x00; // DATOS1
txBuffer[6] = 0x00; // DATOS2
txBuffer[7] = 0x00; // DATOS3
txBuffer[8] = txBuffer[1] ^ txBuffer[2] ^ txBuffer[3] ^ txBuffer[4] ^ txBuffer[5] ^ txBuffer[6] ^ txBuffer[7]; // CRC
txBuffer[9] = 0x0A; // EOF
printf("TX - Sending frame\r\n");
HAL_UART_Transmit(&UART_RS485, txBuffer, framelength, 1000);
// Activate receiving status
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0);
HAL_UART_Receive(&UART_RS485, rxBuffer, framelength, 1000);
printf("RX - Reception Completed:\r\n");
for(int j=0; j<framelength; j++)
{
printf("Byte %d: %02X\r\n", j, rxBuffer[j]);
}
HAL_Delay(3000);
}
UART Configuration
static void MX_USART1_UART_Init(void)
{
UART_RS485.Instance = USART1;
UART_RS485.Init.BaudRate = 115200;
UART_RS485.Init.WordLength = UART_WORDLENGTH_8B;
UART_RS485.Init.StopBits = UART_STOPBITS_1;
UART_RS485.Init.Parity = UART_PARITY_NONE;
UART_RS485.Init.Mode = UART_MODE_TX_RX;
UART_RS485.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UART_RS485.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&UART_RS485) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
I should be receiving a frame starting with 0x44 and ending with 0x0A based on the cell protocol. However, this is what I receive:
I have tried many different UART parameters, many different pin configurations and tried using a 120 ohm and 220 ohm resistors between A and B lines but nothing works.
What am I missing?
I suggest you to see: Uart Status Register of you STM32 uc (because you could see UART errors like parity error, frame error and buffer overflow). In my work UART errors very often were related to buffer overflow because uc usually have a very small buffer (for ATmega 32 - 2 bytes).
Also i suggest you to use mode with parity bit, because it a data check in any case.
Also have you calculate you UART error (depends on you clock frequency and UART speed). You also could select UART speed with 0 % of errors.
You could see article about status register and baud rate here: http://www.micromouseonline.com/2009/12/31/stm32-usart-basics/
I am currently working on a project that involves the STM32f0Discovery board and this fingerprint scanner, which uses UART communication. To initialize the UART, I do the following:
void init_uart(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
Then to send/receive a byte I do the following:
void writechar(char c) {
while((USART1 -> ISR & USART_ISR_TC) != USART_ISR_TC);
USART1 -> TDR = c;
}
char readchar(void) {
return USART_ReceiveData(USART1);
}
To test this, I sent the OPEN command byte-by-byte through a for-loop, then the LEN-ON command the same method, which has no results. When reading for an ACK after the OPEN command, the results read are just an empty array of char bytes.
So, my question is, is my initialization the error? Or is the error in the reading/writing? Or could it be something else altogether?
Are you getting the ACK response ? If you are not then there is probably a configuration or wiring problem. I would suggest you try connecting the serial pins to a serial-usb converter
(FTDI such as this :Click here)
and use an app like Putty or YAT to send commands (ACK) to and from your stm. Try using the same configuration the scanner has if that doesn't work its a problem with your config if it does work its a problem scanner side.
I am trying to implement SPI on STM32F3 Discovery board using standard peripheral library. I don't want to use HAL drivers(It is a constraint). I am not able to figure what I am missing. I am implementing the SPI in slave mode. Below is the SPI configuration and code in main function.
void main() {
/* Initializes the SPI communication */
SPI_I2S_DeInit(SPIx);
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_Init(SPIx, &SPI_InitStructure);
/* Initialize the FIFO threshold */
SPI_RxFIFOThresholdConfig(SPIx, SPI_RxFIFOThreshold_QF);
While(1){
// Start SPI transfer
/* DMA channel Rx of SPI Configuration */
DMA_InitStructure.DMA_BufferSize = NumberOfByte;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPIx_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(SPIx_RX_DMA_CHANNEL, &DMA_InitStructure);
/* DMA channel Tx of SPI Configuration */
DMA_InitStructure.DMA_BufferSize = NumberOfByte;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPIx_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_Init(SPIx_TX_DMA_CHANNEL, &DMA_InitStructure);
/* Enable the SPI Rx and Tx DMA requests */
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE);
/* Enable the SPI peripheral */
SPI_Cmd(SPIx, ENABLE);
/* Enable the DMA channels */
DMA_Cmd(SPIx_RX_DMA_CHANNEL, ENABLE);
DMA_Cmd(SPIx_TX_DMA_CHANNEL, ENABLE);
/* Wait the SPI DMA transfers complete or time out */
while (DMA_GetFlagStatus(SPIx_RX_DMA_FLAG_TC) == RESET)
{}
TimeOut = USER_TIMEOUT;
while ((DMA_GetFlagStatus(SPIx_TX_DMA_FLAG_TC) == RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
/* The BSY flag can be monitored to ensure that the SPI communication is complete.
This is required to avoid corrupting the last transmission before disabling
the SPI or entering the Stop mode. The software must first wait until TXE=1
and then until BSY=0.*/
TimeOut = USER_TIMEOUT;
while ((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
TimeOut = USER_TIMEOUT;
while ((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
/* Clear DMA1 global flags */
DMA_ClearFlag(SPIx_TX_DMA_FLAG_GL);
DMA_ClearFlag(SPIx_RX_DMA_FLAG_GL);
/* Disable the DMA channels */
DMA_Cmd(SPIx_RX_DMA_CHANNEL, DISABLE);
DMA_Cmd(SPIx_TX_DMA_CHANNEL, DISABLE);
/* Disable the SPI peripheral */
SPI_Cmd(SPIx, DISABLE);
/* Disable the SPI Rx and Tx DMA requests */
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, DISABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, DISABLE);
}}
SPI configuration is as follows :
static void SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the SPI peripheral */
RCC_APB2PeriphClockCmd(SPIx_CLK, ENABLE);
/* Enable the DMA peripheral */
RCC_AHBPeriphClockCmd(SPI_DMAx_CLK | TIM_DMAx_CLK, ENABLE);
/* Enable the TIM peripheral */
RCC_APB1PeriphClockCmd(TIMx_CLK, ENABLE);
/* Enable SCK, MOSI, MISO and NSS GPIO clocks */
RCC_AHBPeriphClockCmd(SPIx_SCK_GPIO_CLK | SPIx_MISO_GPIO_CLK |
SPIx_MOSI_GPIO_CLK |
SPIx_NSS_GPIO_CLK , ENABLE);
/* Enable TIM DMA trigger clock */
RCC_AHBPeriphClockCmd(TIMx_TRIGGER_GPIO_CLK, ENABLE);
/* SPI pin mappings */
GPIO_PinAFConfig(SPIx_SCK_GPIO_PORT, SPIx_SCK_SOURCE, SPIx_SCK_AF);
GPIO_PinAFConfig(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_SOURCE, SPIx_MOSI_AF);
GPIO_PinAFConfig(SPIx_MISO_GPIO_PORT, SPIx_MISO_SOURCE, SPIx_MISO_AF);
GPIO_PinAFConfig(SPIx_NSS_GPIO_PORT, SPIx_NSS_SOURCE, SPIx_NSS_AF);
/* TIM capture compare pin mapping */
GPIO_PinAFConfig(TIMx_TRIGGER_GPIO_PORT, TIMx_TRIGGER_SOURCE,
TIMx_TRIGGER_AF);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN;
GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStructure);
/* SPI MOSI pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_MOSI_PIN;
GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* SPI MISO pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_MISO_PIN;
GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStructure);
/* SPI NSS pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_NSS_PIN;
GPIO_Init(SPIx_NSS_GPIO_PORT, &GPIO_InitStructure);
/* Configure the TIM channelx capture compare as DMA Trigger */
GPIO_InitStructure.GPIO_Pin = TIMx_TRIGGER_PIN;
GPIO_Init(TIMx_TRIGGER_GPIO_PORT, &GPIO_InitStructure);
/* SPI configuration -------------------------------------------------------
*/
SPI_I2S_DeInit(SPIx);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DATASIZE;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
/* DMA Configuration -------------------------------------------------------
*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
}
Can anyone tell me where the problem is? I have Master code in HAL drivers on other board that is working fine(Tested). So there is no issue in master side. Slave side is the problem.
your code is in While(1) where you are configuring and initializing the SPI peripheral. make it in a separate function and initialize and configure only once. Also first try it without DMA and later put DMA back in.
I have an issue with STM32F0 Discovery.
I am using I2C1 (like master) to send start condition and address to I2C2 (slave) on the same board.
I am able to generate propertly the signal but the IC2 (slave) is not able to generate an ACK on 9th clk
What's wrong?
Here my code about the setup:
void set_I2C(void){
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Configure the I2C clock source. The clock is derived from the HSI */
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);
//Configure pins: SCL and SDA ------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);
I2C_Cmd(I2C1, DISABLE);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x40;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing =0xB0420F13; //100KHz
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
//Set up of I2C2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_1);
//Configure pins: SCL and SDA ------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C2);
I2C_Cmd(I2C2, DISABLE);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Disable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x30;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing =0xB0420F13;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C2, &I2C_InitStructure);
I2C_Cmd(I2C2, ENABLE);
I2C_ITConfig(I2C2, I2C_AcknowledgedAddress_7bit, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the I2C2 interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = I2C2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
I had the same problem. It was caused by absence of the required for I2C external pull-up resistors. You can't just use an internal MCU's pull-ups. You MUST use external ones.
Detailed explanation is provided in these articles:
http://www.robot-electronics.co.uk/acatalog/I2C_Tutorial.html
https://electronics.stackexchange.com/questions/1849/is-there-a-correct-resistance-value-for-pull-up-resistors
I run into similar issue.
In my case the solution was to add a HAL_I2C_EnableListen_IT() after initialization to activate I2C slave (I am using HAL libraries, but you can check what the above function does in details).