I am running USART3, on 921600 BaudRate, using RTS CTS, I am always facing system hang when I try to do RX and TX simultaneously. I have pasted the main and IRQ code. IRQ is designed to Transmit a char 'A' while dropping all received data. Hangs happens when we disable USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
Uart_Configuration()...
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART3, &USART_ClockInitStructure);
USART_InitStructure.USART_Mode = (USART_Mode_Tx|USART_Mode_Rx);
USART_InitStructure.USART_BaudRate = u32BaudRate;
USART_OverSampling8Cmd(USART3, DISABLE);
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3,USART_IT_TXE, DISABLE);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_Cmd(USART3, ENABLE);
Main.c ...
uint8_t UART_TransmitData(void)
{
if(u8IntTxFlag==1)
{
u8IntTxFlag=0;
USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
return TRUE;
}
return FALSE;
}
void USART3_IRQHandler(void)
{
/* Implemented full duplex serial communication */
/* UART RX */
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
USART_ReceiveData(USART3);
}
/* UART TX */
if(USART_GetITStatus(USART3, USART_IT_TXE) != RESET)
{
if(USART_GetFlagStatus(USART3, USART_FLAG_CTS) == RESET)
{
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
USART_SendData(USART3, 'A');
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
USART_ClearFlag(USART3, USART_FLAG_TC);
USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
u8IntTxFlag=1;
}
else
{
USART_ClearFlag(USART3, USART_FLAG_CTS);
}
}
}
int main(void)
{
RCC_ClocksTypeDef RCC_Clocks;
RCC_Configuration();
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 2000);
NVIC_Configuration();
Init_GPIOs();
SerialUARTConfig(921600, 0, 1, 8, 1);
while(1)
{
UART_TransmitData();
f_SleepMs(5);
}
return 0;
}
Maybe the USART_IT_TXE interrupt happens before you disable it? So the "Tx empty" interrupt pending flag is already set and there is no procedure inside your IRQHandler to clear that flag.
Related
I'm using an STM32F030R8 to perform RS485 communications connected to a AD3485. So far I've been able to get it to transmit just fine, but when I setup an interrupt handler it seems like the interrupt is being triggered by my chip's own transmissions and stops all further transmissions.
Have I missed setting or clearing a flag somewhere? Did I miss something in my RS485 init step? Should I be clearing a flag when my transmissions inevitably trigger the interrupt request?
Below I've included a very stripped down, but complete version of code I'm using for transmission of data, as well as a capture of data that I'm seeing come out of the RS485 chip that I have hooked up to pins A9 A10 and A12.
Here's the code:
#include "stm32f0xx_conf.h"
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_usart.h>
void SysTick_Handler(void) {
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0xAC);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, 0x44);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, 0x04);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, 0x53);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
void RS485_Init(){
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_12; // Pins 9 (TX) 10 (RX) 12 (DE) are used
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // the pins are configured as alternate function so the USART peripheral has access to them
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // this defines the IO speed and has nothing to do with the baudrate!
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // this defines the output type as push pull mode (as opposed to open drain)
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // this activates the pullup resistors on the IO pins
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); //
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1);
USART_InitStruct.USART_BaudRate = 38400 ; // the baudrate is set to the value we passed into this init function
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // we want the data frame size to be 8 bits (standard)
USART_InitStruct.USART_StopBits = USART_StopBits_1; // we want 1 stop bit (standard)
USART_InitStruct.USART_Parity = USART_Parity_No; // we don't want a parity bit (standard)
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // we don't want flow control (standard)
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // we want to enable the transmitter and the receiver
USART_Init(USART1, &USART_InitStruct);
USART_HalfDuplexCmd(USART1, ENABLE);
USART_DECmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_SetDEAssertionTime(USART1, 0x4E2);
USART_SetDEDeassertionTime(USART1, 0x4E2);
USART_DEPolarityConfig(USART1, USART_DEPolarity_High);
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct); //When I comment this out, I'm able to transmit normally, but without an ISR receiving bytes will be difficult
USART_Cmd(USART1, ENABLE);
}
//This function handles USART1 global interrupt request.
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
unsigned char USART_Temp_Byte;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
USART_Temp_Byte = (unsigned char) USART_ReceiveData(USART1); //receive a char
}
}
int main(void)
{
RS485_Init();
SysTick_Config(SystemCoreClock/1000);
while(1);
}
And here's a capture of when I have the interrupt enabled (first capture), vs when I comment out NVIC_Init(&NVIC_InitStruct); and don't have an ISR triggering:
This is one of the core principles of half/full duplex communications methods. RS485, which is a physical layer standard, allows transmitters to receive their own data. This is useful for other standards (software layer), such as J1708. Since there isn't a hard requirement for a single master and multiple slaves, each node can initiate a communication. If two modules start to talk at the same time, there needs to be a scheme to detect and handle bus contentions/collisions. With RS485, you have a dominate (driven) state and a recessive (non-driven) state. When the transmitter begins to transmit, you monitor to see if what you receive matches what you sent, if it doesn't, most likely another device was trying to transmit as the same time. This works because when you switch from a dominate state to recessive, the bus will either return to the recessive state (no collision), or remain in the dominate state due to another receiver holding the line (collision). When this happens, you stop any further transmission and either start receiving or monitor the bus for an idle state. Most protocols, like J1708, use a pseudo random generator based on your address to calculate a retry delay, which prevents the same two modules from constantly colliding.
Long story short: the fact that you are receiving what you transmit is a good thing. I would suggest you use the interrupt to compare the byte just transmitted and the byte just received and if they match, send the next byte, else terminate and try again after the next idle state is detected. Since it's the same interrupt routine, you need to set a flag indicating when you are transmitting and steer the interrupt logic to handle the comparisons (Tx portion) or handle normal recieve (Rx portion)
I'm adding this answer as an update to getting half duplex comms working with this particular chip. With this configuration I was able to both transmit and receive. Special Thanks to Joe Thomas for putting me on the right track.
#include "stm32f0xx_conf.h"
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_usart.h>
void Transmit(void){
USART_Cmd(USART1, DISABLE);
USART_DECmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
USART_Cmd(USART1, ENABLE);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0xAC);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0x44);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0x04);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0x53);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_Cmd(USART1, DISABLE);
USART_DECmd(USART1, DISABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
USART_Cmd(USART1, ENABLE);
}
void SysTick_Handler(void) {
}
void RS485_Init(){
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1);
USART_DeInit(USART1);
USART_StructInit(&USART_InitStruct);
USART_InitStruct.USART_BaudRate = 38400 ;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
USART_HalfDuplexCmd(USART1, DISABLE);
USART_DECmd(USART1, DISABLE);
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_SetDEAssertionTime(USART1, 0x4E2);
USART_SetDEDeassertionTime(USART1, 0x4E2);
USART_DEPolarityConfig(USART1, USART_DEPolarity_High);
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
unsigned char USART_Temp_Byte;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
USART_Temp_Byte = (unsigned char) USART_ReceiveData(USART1); //receive a char
if(0x53 == USART_Temp_Byte){
Transmit();
}
}
}
int main(void)
{
RS485_Init();
SysTick_Config(SystemCoreClock/1000);
while(1){};
}
I have smt32l1xx board and this code below is not working. Debugger shows pinA5 is set, but diode connected to this pin is still not lightening. I dont know why. Even i add delay after setting bit it is not working. diode is connected to PA5 and GND on board.
#include <stm32l1xx.h>
#define ENABLE 1
#define DISABLE 0
void TIM2_IRQHandler() //interrupt
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5))
GPIO_ResetBits(GPIOA, GPIO_Pin_5); //LED OFF
else
GPIO_SetBits(GPIOA, GPIO_Pin_5); //LED ON <- im here and still nothing
}
}
int main(void)
{
/* gpio init struct */
GPIO_InitTypeDef gpio;
TIM_TimeBaseInitTypeDef tim;
NVIC_InitTypeDef nvic;
/* reset rcc */
RCC_DeInit();
RCC_APB2PeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_StructInit(&gpio);
/* use pin 0 */
gpio.GPIO_Pin = GPIO_Pin_5;
/* mode: output */
gpio.GPIO_Mode = GPIO_Mode_OUT;
/* apply configuration */
GPIO_Init(GPIOA, &gpio);
TIM_TimeBaseStructInit(&tim); //timer
tim.TIM_CounterMode = TIM_CounterMode_Up;
tim.TIM_Prescaler = 64000 - 1;
tim.TIM_Period = 1000 - 1;
TIM_TimeBaseInit(TIM2, &tim);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
nvic.NVIC_IRQChannel = TIM2_IRQn; //interrupt
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
while (1)
{
}
/* never reached */
return 0;
}
To make sure that your hardware is properly initialized, you should use STM32CubeMX.
It seems that the GPIOA clock is on the AHB bus, however you call RCC_APB2PeriphClockCmd which is for APB2. So try to use the equivalent for AHB something like RCC_AHBPeriphClockCmd
I try to implement a timer interrupt on a STM32F429I, but I had no success yet.
The Timer runs fine (observed with debugger) but the interrupt function never gets a call. Also the system seems to hang if I activate the interrupt and then call the function GPIO_WriteBit(), at least when I use the debugger and the function gets called, the debugger hangs. Here is the code so far:
#include "stm32f4xx.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_syscfg.h"
//****************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* pin configuration */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM2); // PA6 TIM2_CH1
}
//****************************************************************************
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
int i;
/* Enable TIM2 Peripheral clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 60000;
TIM_TimeBaseStructure.TIM_Period = 1500; //1Hz Interrupt frequency
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_Cmd(TIM2, ENABLE);
// Likely will interrupt initially unless we clear it
for(i=0; i<3; i++)
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}
//****************************************************************************
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
GPIO_ToggleBits(GPIOA, GPIO_Pin_6);
}
}
//****************************************************************************
void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//****************************************************************************
int main(void)
{
SystemInit();
if (SysTick_Config(SystemCoreClock / 1000))
{
/* Capture error */
while (1);
}
NVIC_Configuration();
GPIO_Configuration();
TIM2_Configuration();
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET);
while(1) {
}
}
//******************************************************************************
I have a STM32F407x. Is it possible to have a PWM Signal on a Pin and at the same time getting a timer interrupt if the UPPER value is reached? I tried the following code, but I only get once an interrupt (count stays at 1 forever if I use the debugger), but the PWM Signal is still available at PB6:
volatile int count=0;
void TM_LEDS_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
/* Clock for GPIOB */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
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(GPIOB, &GPIO_InitStruct);
}
void TM_TIMER_Init(void) {
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_BaseStruct.TIM_Prescaler = 100;
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_Period = 256;
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_BaseStruct);
}
void TM_PWM_Init(void) {
TIM_OCInitTypeDef TIM_OCStruct;
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 = 150; /* 25% duty cycle */
TIM_OC1Init(TIM4, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
/* Clear Interrupt */
for(int i=0; i<3; i++)
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
/* Enable Interrupt */
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
void configNVIC(void)
{
NVIC_InitTypeDef initNVICStruct;
/* Enable the TIM2 global Interrupt */
initNVICStruct.NVIC_IRQChannel = TIM4_IRQn;
initNVICStruct.NVIC_IRQChannelPreemptionPriority = 1;
initNVICStruct.NVIC_IRQChannelSubPriority = 3;
initNVICStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&initNVICStruct);
}
void TIM4_IRQHandler(void) //This Interrupt changes changes state from x to x+-1
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
count++;
}
}
int main(void) {
/* Initialize system */
SystemInit();
configNVIC();
/* Init leds */
TM_LEDS_Init();
/* Init timer */
TM_TIMER_Init();
/* Init PWM */
TM_PWM_Init();
int i=0;
while (1) {
i=count;
}
}
If you're trying to count pulses or stop at a certain pulse this post may help
Stop PWM output after N steps
I am working with the following evaluation board: SZWB-sail, STM32f103VET6 KIT v3.1
I want to use the stm32f103 usart in synchronous mode, and I used
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\USART\Synchronous
I modified the code in an attempt to use USART2/SPI1, as opposed to the working code provided via STMicro, which uses USART1/SPI1.
The README for this example states that:
"USARTy and SPIy can be USART1 and SPI1 or USART2 and SPI3, depending on the STMicroelectronics EVAL board you are using."
Despite this, I attempted to physically connect USART2 Tx/Rx/Ck pins (PA2,PA3,PA4) to SPI1 SCK/MISO/MOSI (PA5,PA6,PA7). Is there a software reason for why this won't work? Or might it be hardware connections on the eval board?
Here is my code:
int main(void)
{
SystemInit();
Init_NVIC();
/* System Clocks Configuration */
RCC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
SPI_Configuration();
USART_Configuration();
while(NbrOfDataToRead2--)
{
USART2_Send_Byte(TxBuffer1[TxCounter1++]);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
{
}
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
{
}
RxBuffer2[RxCounter2++] = SPI_I2S_ReceiveData(SPI1);
}
USART2_Receive_Byte();
while(NbrOfDataToRead1--)
{
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)== RESET)
{
}
SPI_I2S_SendData(SPI1, TxBuffer2[TxCounter2++]);
USART2_Send_Byte(DYMMY_BYTE);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
{
}
while(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET)
{
}
RxBuffer1[RxCounter1++] = USART2_Receive_Byte();
}
TransferStatus1 = Buffercmp(TxBuffer1, RxBuffer2, TxBufferSize1);
TransferStatus2 = Buffercmp(TxBuffer2, RxBuffer1, TxBufferSize2);
while(1)
{
}
}
void Init_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void RCC_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure1,GPIO_InitStructure2;
GPIO_InitTypeDef GPIO_InitStructure3,GPIO_InitStructure4,GPIO_InitStructure5,GPIO_InitStructure6;
/* Configure USART1 Rx as input floating */
GPIO_InitStructure1.GPIO_Pin =GPIO_Pin_10;
GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure1);
/* Configure USART1 Tx as alternate function push-pull */
GPIO_InitStructure2.GPIO_Pin =GPIO_Pin_9;
GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure2);
/* Configure USART2 Rx as input floating */
GPIO_InitStructure3.GPIO_Pin =GPIO_Pin_3;
GPIO_InitStructure3.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure3.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure3);
/* Configure USART2 Tx as alternate function push-pull */
GPIO_InitStructure4.GPIO_Pin =GPIO_Pin_2;
GPIO_InitStructure4.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure4.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure4);
/* Configure USART2 Ck as alternate function push-pull */
GPIO_InitStructure5.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure5.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure5.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure5);
/* Configure SPI1 pins: SCK, MISO and MOSI */
GPIO_InitStructure6.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure6);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure1,USART_InitStructure2;
USART_ClockInitTypeDef USART_ClkInitStructure;
USART_InitStructure1.USART_BaudRate = 115200;
USART_InitStructure1.USART_WordLength =USART_WordLength_8b ;
USART_InitStructure1.USART_StopBits = USART_StopBits_1;
USART_InitStructure1.USART_Parity = USART_Parity_No;
USART_InitStructure1.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure1.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USART1,&USART_InitStructure1);
//USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1,ENABLE);
USART_ClkInitStructure.USART_Clock=USART_Clock_Enable;
USART_ClkInitStructure.USART_CPOL=USART_CPOL_High;
USART_ClkInitStructure.USART_CPHA=USART_CPHA_2Edge;
USART_ClkInitStructure.USART_LastBit=USART_LastBit_Enable;
USART_ClockInit(USART2, &USART_ClkInitStructure);
USART_InitStructure2.USART_BaudRate = 115200;
USART_InitStructure2.USART_WordLength =USART_WordLength_8b ;
USART_InitStructure2.USART_StopBits = USART_StopBits_1;
USART_InitStructure2.USART_Parity = USART_Parity_No;
USART_InitStructure2.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure2.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART2 */
USART_Init(USART2,&USART_InitStructure2);
//USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
/* Enable the USART2 */
USART_Cmd(USART2,ENABLE);
}
void SPI_Configuration(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_StructInit(&SPI_InitStructure);
SPI_I2S_DeInit(SPI1);
/* SPIy Config */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
/* Configure SPIy */
SPI_Init(SPI1, &SPI_InitStructure);
SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
/* SPIy enable */
SPI_Cmd(SPI1, ENABLE);
}
You are mixing polling mode with interrupt mode. This SPI configuration code is intended for SPI interrupt mode. Hence, SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) should not be used, because this is a function intended for Polling-Mode.
Instead, I believe you can use SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); in conjunction with SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) and SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) (to clear any potential Error pending bits, just in-case).
Also, you might want to post your USART2_Send_Byte() code so we know what exactly it's doing, and whether it's calling any other functions...but go ahead and try this first to see if it fixes your problem.
SPI1 conflicts with USART2 synchronization mode.
SPI2 conflicts with USART3 synchronization mode.
There is no conflict between SPI1/2 and USART1 synchronization modes.