How to receive packets on the MCU's serial port? - embedded

Consider this code running on my microcontroller unit(MCU):
while(1){
do_stuff;
if(packet_from_PC)
send_data_via_gpio(new_packet); //send via general purpose i/o pins
else
send_data_via_gpio(default_packet);
do_other_stuff;
}
The MCU is also interfaced to a PC via a UART.Whenever the PC sends data to the MCU, the new_packet is sent,
otherwise the default_packet is sent.Each packet can be 5 or more bytes with a pre defined packet structure.
My question is:
1.Should i receive the entire packet from PC using inside the UART interrut service routine (ISR)? In this case, i have to implement
a state machine inside the ISR to assemble the packet (which can be lengthy with if-else or switch-case blocks).
OR
2.Have the PC send some sort of a REQUEST command (one byte),detect it in my ISR set a flag, disable UART interrupt alone and form the packet in my while(1) loop by checking for the flag and polling the UART?In this case the UART interrupt would be re-enabled in the while(1) loop after the entire packet is formed.

Those are not the only two choices, and the second one seems suboptimal.
My first approach would be to a simple circular queue, and push bytes into it from the ISR and read bytes from in your main loop. That way you have a small and simple ISR and you and do the processing in your main loop without disabling interrupts.
The first choice is possible assuming you can code the ISR sensibly. You probably want to have timeouts when dealing with constructing packets; you need to be able to handle that correctly in your ISR. It depends on the line speed, the speed of your MCU and what else you need to do.
Update:
Doing it in the ISR is certainly reasonable. However, using a circular queue is pretty straightforward with a standard implementation in your bag of tricks. Here is a circular queue implementation; readers and writers can operate independently.
#ifndef ARRAY_ELEMENTS
#define ARRAY_ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
#endif
#define QUEUE_DEFINE(name, queue_depth, type) \
struct queue_type__##name { \
volatile size_t m_in; \
volatile size_t m_out; \
type m_queue[queue_depth]; \
}
#define QUEUE_DECLARE(name) struct queue_type__##name name
#define QUEUE_SIZE(name) ARRAY_ELEMENTS((name).m_queue)
#define QUEUE_CALC_NEXT(name, i) \
(((name).i == (QUEUE_SIZE(name) - 1)) ? 0 : ((name).i + 1))
#define QUEUE_INIT(name) (name).m_in = (name).m_out = 0
#define QUEUE_EMPTY(name) ((name).m_in == (name).m_out)
#define QUEUE_FULL(name) (QUEUE_CALC_NEXT(name, m_in) == (name).m_out)
#define QUEUE_NEXT_OUT(name) ((name).m_queue + (name).m_out)
#define QUEUE_NEXT_IN(name) ((name).m_queue + (name).m_in)
#define QUEUE_PUSH(name) ((name).m_in = QUEUE_CALC_NEXT((name), m_in))
#define QUEUE_POP(name) ((name).m_out = QUEUE_CALC_NEXT((name), m_out))
Use it like this:
QUEUE_DEFINE(bytes_received, 64, unsigned char);
QUEUE_DECLARE(bytes_received);
void isr(void)
{
/* Move the received byte into 'c' */
/* This code enqueues the byte, or drops it if the queue is full */
if (!QUEUE_FULL(bytes_received)) {
*QUEUE_NEXT_IN(bytes_received) = c;
QUEUE_PUSH(bytes_received);
}
}
void main(void)
{
QUEUE_INIT(bytes_received);
for (;;) {
other_processing();
if (!QUEUE_EMPTY(bytes_received)) {
unsigned char c = *QUEUE_NEXT_OUT(bytes_received);
QUEUE_POP(bytes_received);
/* Use c as you see fit ... */
}
}
}

Related

STM32 reading variables out of Received Buffer with variable size

I am not really familiar with programming in STM32. I am using the micro controller STM32F303RE.
I am receiving data via a UART connection with DMA.
Code:
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuf, RxBuf_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
I am writing the value into a Receiving Buffer and then transfer it into a main buffer. This function and declaration is down before the int main(void).
#define RxBuf_SIZE 100
#define MainBuf_Size 100
uint8_t RxBuf[RxBuf_SIZE];
uint8_t MainBuf[MainBuf_Size];
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart,uint16_t Size){
if( huart -> Instance == USART2){
memcpy (MainBuf, RxBuf, Size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuf, RxBuf_SIZE);
}
for (int i = 0; i<Size; i++){
if((MainBuf[i] == 'G') && (MainBuf[i+1] == 'O')){
RecieveData();
HAL_UART_DMAStop(&huart2);
}
}
}
I receive know the data into a buffer and it stops as soon as "GO" is transmitted. Until this point it is working. The function ReceiveData() should then transform this buffer to the variables. But it isn't working for me.
Now I want to transform this received data with "breakpoints" into variables.
So I want to send: "S2000S1000S1S10S2GO".
I always have 5 variables. (in this case: 2000, 1000, 1, 10, 2) I want to read the data out of the string and transform it into an uint16_t to procude. The size/ length of the variables could be changed. That's why I tried to use like some breakpoint.

UART Serial Bridge using MSP430 FR5994

I am trying to create a UART bridge using MSP430. I have a sensor sending strings to the MSP430 which I intend to send to my PC. Additionally, the sensor responds to commands which I intend to send using my PC through the MSP430 bridge. The commands I am sending to the sensor reach it without any flaw. However, the messages sent by the sensor reach the TXBUF of the UART connected to my PC but does not appear on the terminal. On checking the registers I see 0x000A on the TXBUF but it appears to recieve all the chahracters. But nothing is printed.
I am using the following code:
#include <msp430.h>
unsigned char *msg;
unsigned char i=0 , j=0;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
// Pin Initialization
P6SEL1 |= BIT1;
P6SEL0 &= ~BIT1;
P6SEL1 |= BIT0;
P6SEL0 &= ~BIT0;
P2SEL1 |= BIT5;
P2SEL0 &= ~BIT5;
P2SEL1 |= BIT6;
P2SEL0 &= ~BIT6;
PM5CTL0 &= ~LOCKLPM5;
// UART Initialization
UCA1CTLW0 |= UCSWRST;
UCA1CTLW0 |= UCSSEL__SMCLK; // Using 1 MHZ clock
UCA3CTLW0 |= UCSWRST;
UCA3CTLW0 |= UCSSEL__SMCLK;
UCA3BRW = 6; // Baud Rate set to 9600
UCA3MCTLW = UCOS16 | UCBRF_8 | 0x2000;
UCA1BRW = 6;
UCA1MCTLW = UCOS16 | UCBRF_8 | 0x2000;
UCA3CTLW0 &= ~UCSWRST;
UCA1CTLW0 &= ~UCSWRST;
UCA3IE |= UCRXIE;
UCA1IE |= UCRXIE;
__enable_interrupt(); // Interrupt enable
while (1)
{}
}
// UART A3 connected to the PC.
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=EUSCI_A3_VECTOR
__interrupt void USCI_A3_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(EUSCI_A3_VECTOR))) USCI_A3_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA3IV, USCI_UART_UCTXCPTIFG))
{
case USCI_NONE: break;
case USCI_UART_UCRXIFG:
while(!(UCA3IFG&UCTXIFG));
UCA1TXBUF = UCA3RXBUF;
__no_operation();
break;
case USCI_UART_UCTXIFG: break;
case USCI_UART_UCSTTIFG: break;
case USCI_UART_UCTXCPTIFG: break;
default: break;
}
}
// UART A1 connected to the sensor.
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=EUSCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(EUSCI_A1_VECTOR))) USCI_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
{
case USCI_NONE: break;
case USCI_UART_UCRXIFG:
while(!(UCA1IFG&UCTXIFG)); //Trying to read a string
{
*(msg+i) = UCA1RXBUF;
j = *(msg+i);
UCA3TXBUF = j;
i++;
}
break;
case USCI_UART_UCTXIFG: break;
case USCI_UART_UCSTTIFG: break;
case USCI_UART_UCTXCPTIFG: break;
default: break;
}
}
Please help.
Thanks in advance.
First, the problems that I see with your listing:
(p1) Even though the baud rates of both UARTs are the same, your design does not make use of proper (see problem 3 below) buffering in the event that both the PC and the sensor is sending data at the same time. To make matters worse, both your ISRs contain blocking while loops that don't buffer and only waste time until the interrupt flags clears.
(p2) Your source (shown below) is likely coded in error:
while(!(UCA1IFG&UCTXIFG)); //Trying to read a string
{
*(msg+i) = UCA1RXBUF;
j = *(msg+i);
UCA3TXBUF = j;
i++;
}
because the body of the while loop is actually empty due to the trailing ";" so the code within the open/closing brackets that follows is not part of the while loop.
(p3) The pointer variable msg was never initialized. Most likely it points to random heap memory or unused portion of the stack, so the program doesn't crash right away. Eventually, it would because the variable i is incremented but never decremented, so memory is "one time used" by the sensor ISR.
My suggestions:
(s1) Declare two buffers, one for data arriving from the PC and the other for data arriving from the sensor. Remove the "unsigned char *msg" and replace with something like this:
unsigned char pc_data[256];
unsigned char sensor_data[256];
The size 256 is on purpose to create a poor-mans circular buffer when used with an 8-bit index variable. When the variable reaches 255 and is incremented, it will simply roll back to 0. In this case both i and j as you already declared can be used, but maybe pc_data_index and sensor_data_index would be better understood. You also need two more variables for the size of the buffer, maybe pc_data_count and sensor_data_count. If your procssor cannot afford this much buffer space, then decrease to a modular amount (i.e., 2^BUFSIZE, where BUFSIZE = 32) and use the modular operator when updating the index like this:
pc_data_index = (pc_data_index + 1) % BUFSIZE;
(s2) Change both ISR routines to process both the USCI_UART_UCRXIFG and USCI_UART_UCTXIFG interrupt events. The ISRs should not contain any loops, simply buffer data or write data out from buffer. Here is an example:
switch(__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
{
case USCI_NONE: break;
case USCI_UART_UCRXIFG:
// Byte was received from sensor, so buffer it
sensor_data[sensor_data_count++] = UCA1RXBUF;
sensor_data_index = (sensor_data_index + 1) % BUFSIZE;
// Enable the TX interrupts to send the buffered data
UCA1IE |= UCTXIE;
break;
case USCI_UART_UCTXIFG:
// Sensor UART is ready to send next byte
UCA3TXBUF = sensor_data[sensor_data_index];
sensor_data_count--;
// Disable the TX interrupt if no more data to send
if (sensor_data_count == 0) UCA1IE &= ~UCTXIE;
break;

STM32 Nucleo EEPROM Emulator ee_init issue

I am working on trying to get the EEPROM Emulator from stm32 working. I have followed the example given for a stm32 l47x board however I am still running into issues. When I call EE_init I end up running into a stack overflow. I am not too familiar with this emulator and am using the default configurations from the example.
This is how I am initializing everything.
EE_Status ee_status = EE_OK;
/* Enable and set FLASH Interrupt priority */
/* FLASH interrupt is used for the purpose of pages clean up under interrupt */
HAL_NVIC_SetPriority(FLASH_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FLASH_IRQn);
HAL_FLASH_Unlock();
if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) == RESET)
{
/* Blink LED_OK (Green) twice at startup */
LEDInterface_toggleColor(GREEN);
HAL_Delay(100);
LEDInterface_toggleColor(NONE);
HAL_Delay(100);
LEDInterface_toggleColor(GREEN);
HAL_Delay(100);
LEDInterface_toggleColor(NONE);
ee_status = EE_Init(EE_FORCED_ERASE);
if(ee_status != EE_OK)
{
while(1);
}
This is the eeprom_emul_conf.h settings which I also have not changed
/* Configuration of eeprom emulation in flash, can be custom */
#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define START_PAGE_ADDRESS 0x08100000U /*!< Start address of the 1st page in flash, for EEPROM emulation */
#else
#define START_PAGE_ADDRESS 0x08080000U /*!< Start address of the 1st page in flash, for EEPROM emulation */
#endif
#define CYCLES_NUMBER 1U /*!< Number of 10Kcycles requested, minimum 1 for 10Kcycles (default),
for instance 10 to reach 100Kcycles. This factor will increase
pages number */
#define GUARD_PAGES_NUMBER 2U /*!< Number of guard pages avoiding frequent transfers (must be multiple of 2): 0,2,4.. */
/* Configuration of crc calculation for eeprom emulation in flash */
#define CRC_POLYNOMIAL_LENGTH LL_CRC_POLYLENGTH_16B /* CRC polynomial lenght 16 bits */
#define CRC_POLYNOMIAL_VALUE 0x8005U /* Polynomial to use for CRC calculation *
/
I am running into the osal_hooks.c file where I am getting stuck in this while loop
#if defined(DOXYGEN)
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
#else
OSAL_WEAK_FN(void, vApplicationStackOverflowHook)( TaskHandle_t xTask, char *pcTaskName )
#endif
{
volatile char * name = pcTaskName;
(void)name;
while (1)
{
;
}
}
Im sure I need to change where I allocate the memory but what is the best way to go about this. Thank you

How Can I Establish UART Communication between 2 Stm32 and produce PWM signal

Edit: I solved UART communication problem but I have new problem getting pwm signal after receiving Transmit Data. I can blink led I can drive relay with transmitted data but I could not produce PWM signal.
maps(120, 1, 1, 250, RxData[4]);
ADC_Left = Yx; __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,ADC_Left);
I used __HAL_TIM_SET_COMPARE function but it doesnt work. I can observe ADC_Left’s value on Debug site but its not work.
I am trying to realize UART communication between 2 stm32. I know there are several topic related with but my question focused another one.
I am reading 2 adc value on stm32 which is only transmit these value and other one only receive these 2 adc value. To do this
MX_USART1_UART_Init();
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // Interrupt Enable
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
char TxData1[10];
..............
TxData1[0] = 0xEA;
TxData1[1] = wData.Byte_1;
TxData1[2] = wData.Byte_2;
TxData1[3] = wData.Byte_3;
TxData1[4] = wData.Right_Adc_Val;
TxData1[5] = wData.Left_Adc_Val;
TxData1[6] = wData.Byte_6;
for(uint8_t i = 1 ; i < 7; i++)
{
wData.Checksum = wData.Checksum + TxData1[i];
}
wData.Checksum_H = (wData.Checksum >> 8)&0xFF;
wData.Checksum_L = (wData.Checksum)&0xFF;
TxData1[7] = wData.Checksum_H;
TxData1[8] = wData.Checksum_L;
TxData1[9] = 0xAE;
HAL_UART_Transmit_IT(&huart1,(uint8_t*) &TxData1,10);
............
This block sent them I can observate them on Debug screen and using TTL module's Tx Rx pins.
MX_USART1_UART_Init();
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // Interrupt Enable
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
char RxData[10];
while(1){
HAL_UART_Receive_IT(&huart1,(uint8_t*) &RxData,10);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Receive_IT(&huart1,(uint8_t*) &RxData,10);
}
There is no problem up to here but when i getting RxData 0. index , it gives EA . Of course it should be give EA. When the adc data change all the ranking is changing. RxData[0] gives meaningless data. adc value is jumping over the all RxData array.
data locations must always be in the same index. How Can I get these data in stability for ex.
RxData[0]=EA
.
.
RxData[4]= should give adc value. so on.
..
Edit: I tried other mode of UART, DMA (in circular mode) and direct mode were used. I cant receive even 1 byte with DMA .
In your example code, you have an extra & that needs to be removed from both the transmit and receive HAL method calls. Example:
HAL_UART_Transmit_IT(&huart1,(uint8_t*) &TxData1,10);
HAL_UART_Transmit_IT(&huart1,(uint8_t*) TxData1,10);
To avoid this type of error in the future, recommend not using the cast and try something like the following:
uint8_t TxData1[10];
...
HAL_UART_Transmit_IT(&huart1, TxData1, sizeof(TxData1);

How to setup an interrupt driven SPI with stm32F4

I'am using STM32F4 board with CMSIS library and I want setup an interrupt driven SPI, it means an interrupt is triggered each time a byte is sent by the SPI peripheral. The initiaisation function is as below:
void init_SPI1(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5|GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// connect SPI1 pins to SPI alternate function
//GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
//Set chip select high
GPIOA->BSRRL |= GPIO_Pin_4; // set PE4 high
// enable peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/* configure SPI1 in Mode 0
* CPOL = 0 --> clock is low when idle
* CPHA = 0 --> data is sampled at the first edge
*/
SPI_StructInit(&SPI_InitStruct); // set default settings
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // transmit in master mode, NSS pin has to be always high
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; // clock is low when idle
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // data sampled at first edge
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ; // set the NSS management to internal and pull internal NSS high
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
SPI_Init(SPI1, &SPI_InitStruct);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable SPI1*/
SPI_Cmd(SPI1, ENABLE);
return;
}
Then i just loopback SPI_MOSI to SPI_MISO and use a function that transmit the data (a very basic function that takes data from a buffer and then uses CMSIS functions for the transmission). The problem is that when the SPI interrupt is triggered, the program won't get out from the handler. the handler function looks lihe this:
void SPI1_IRQHandler()
{
int a;
a++;
SPI_I2S_ClearITPendingBit(SPI1,SPI_I2S_IT_TXE);
return;
}
Is it a problem in the CMSIS library, or I am not configuring the SPI interrupt in the good way? Please guide me to the right point.
EDIT
This is the function i use for data transmission
void write_SPI1()
{
int i;
for (i=0;i<SPI_TX_MAX; i++)
{
SPI_I2S_SendData(SPI1,spiTxBuff[i]);
SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
}
}
and the interruption deals with the data reception, it just fill spiRxBuff when receiving new data.
void SPI1_IRQHandler()
{
while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)== RESET);
spiRxBuff[spiRxCount]= SPI_I2S_ReceiveData(SPI1);
spiRxCount++;
}
The variable used for Reception / Transmission are declared as below :
uint8_t spiTxBuff[SPI_TX_MAX] = {0x01,0x02,0x03,0x04,0x05,0x06};
uint8_t spiRxBuff[SPI_RX_MAX];
static volatile int spiRxCount= 0; // used in SPI1_IRQHandler
what is strange now is that i'am having {0x01,0x02,0x03,0x05,0x06} in spiRxBuff instead of {0x01,0x02,0x03,0x04,0x05,0x06}, but using debug mode the data in spiRxBuff are correct, what goes wrong in your opinion ?
You did not show the function doing the transmit, so I don't know exactly what are you trying to accomplish
Transmitting in a loop
If you are transmitting from a function (in a loop), then you don't need interrupts at all, just make sure that the TXE flag is set before you transmit. Note that you have to interleave sending and receiving somehow.
void SPI1_Transmit(uint8_t *send, uint8_t *receive, int count) {
while(count-- > 0) {
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)!=SET) {
if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==SET)
*receive++ = SPI_I2S_ReceiveData(SPI1);
}
SPI_I2S_SendData(SPI1, *send++);
}
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)!=SET) {
/* wait for the last incoming byte */
}
*receive++ = SPI_I2S_ReceiveData(SPI1);
}
Transmitting from interrupt
The TXE interrupt flag is set as long as the SPI device is not busy sending. If you don't do something about it in the interrupt handler, it will trigger an interrupt immediately again and again. You can't clear it manually, but by transmitting another byte, and resetting the transmit interrupt enable flag before sending the last byte.
volatile int spi1_tx_count, spi1_rx_count;
uint8_t *spi1_tx_ptr;
volatile uint8_t *spi1_rx_ptr;
/* set these global variables before enabling interrupts */
void SPI1_IRQHandler() {
if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_TXE) == SET) {
if(--spi1_tx_count < 1)
SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE);
SPI_I2S_SendData(SPI1, *spi1_tx_ptr++);
}
if(SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET) {
*spi_rx_ptr++ = SPI_I2S_ReceiveData(SPI1);
spi1_rx_count++;
}
}
Using DMA
The above examples are using processor power and cycles for a task that can be handled by the DMA conroller alone. A lot of (if not all) processor cycles, if you are talking to a peripheral at 2 MBit/s.
See Project/STM32F4xx_StdPeriph_Examples/SPI/SPI_TwoBoards in the library for an example.
Sorry, I haven't noticed at all that you've amended the question. Look like notifications are sent on new comments or answers, but not on edits.
There are multiple problems with your code. In write_SPI1(), I'd enable RX interrupt only once before the loop, there is no need to do it again and again. Also, you should definitely check whether the TX register is available before sending.
void write_SPI1() {
int i;
SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
for (i=0;i<SPI_TX_MAX; i++) {
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)!=SET)
;
SPI_I2S_SendData(SPI1,spiTxBuff[i]);
}
}
It is however a bad idea to wait on a flag in the interrupt handler. If RXNE is the only possible interrupt source, then you can proceed straight to receiving.