我的传入值位于数据包内部,我必须阅读该包,然后使用该包提取实际值。我使用了一些按位运算和Consistative Byte Stuffing Algoritm构成了一个包。

在接收方,当它检测到Uart上有一个传入字节时,MCU将运行ISR。阅读包装。将其发送到解码器函数,该函数返回解码值的数组。

由于我要返回一个数组,因此我不得不使用malloc并且必须使用free(xxx)函数。我了解到在ISR中使用free()是个坏主意。所以我以某种方式编辑了我的代码,并将free(xxx)放入了主循环。

在这里,您会看到我的中断处理程序函数,该函数在每次成功读取后运行。

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

//{2,32,2,140,3,168,100,3,1,16,0} this is an example package.End byte is always 0 and there is no other possible occurrence of 0 in 1 package thanks to the COBS algoritm

count_dooku++; // this variable counts how many interrupt has occurred. Mostly usefull For debuging.  If i use free() inside of this function count_dooku stops at 22 which means after reading 2 packages it stopped. If there is no free() interrupts keep working as they should

if (huart->Instance == USART1)  //current UART
    {

    int a=0;

   if (Rx_indx==0) {for (int i=0;i<30;i++) Rx_Buffer[i]=0;}   //clear Rx_Buffer before receiving new data

    if (Rx_data[0]!=a) //if received data different from  package end byte 0 //
        {
        Transfer_cplt=0;// reset Transfer_cplt value to 0 since we are receiving new package

        Rx_Buffer[Rx_indx++]=Rx_data[0];    //add data to Rx_Buffer
        }
    else            //if received data = 0 which means end of the package
        {

       //now transfer completed, data is ready to read
                 if (Rx_indx==10)  //check the lenght of the package if true continue
                 {
                    for( int i=0; i < 11; i++ ){
                    un_decoded_data[i]=  *( Rx_Buffer + i ) ;
                    }  copy package values from buffer to another array.

                        Transfer_cplt=1;  // mission completed. Pakage is in "un_decoded_data"
                  }
                 Rx_indx=0;  //reset index counter for new data


          }


    }

 HAL_UART_Receive_IT(&huart1, Rx_data, 1);   //activate UART receive interrupt every time

   }


这是我的主循环:

  int main(void)
 {
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); //initialization of uart in stm32f4 hal library

  while (1)
  {

         if (Transfer_cplt==1)  //if buffer data succesfully transfered to un_decoded_data
                         {

                    UnStuffData(un_decoded_data, 11,destination) ; //this is Consistive overhead algortim for decoding package. No problem with this one bc it uses global values

                                    predec_package=  make_predec_package(destination); //this function takes decoded data and makes some bit wise operations. and returns array of values with pointer. So i used malloc and after i am done with it i have to free it (below)
                                    free(destination); // this one is problem. Even if not in the ISR still related to ISR so still causing problems.
                                    for( int i=0; i < 6; i++ ){
                                            decoded_data[i]=     *( predec_package + i ) ;

                                        }
                       }
    }}


以防万一我正在添加返回数组并产生问题的函数。这里是 :

int16_t* make_predec_package( unsigned char *ptr){  //function takes array as input

int8_t n;
uint8_t temp_array[11] = {0};  //temporary array for calculations and also debugging

int16_t  *temporary = calloc(8, sizeof(*temporary));  //temporary must be freed by caller


if(temporary)
{
     for( int i=0; i < 11; i++ ){
        temp_array[i]        =   *( ptr + i );
     }

     n = temp_array[0];

     //here some bitwise calculations...
    temporary[0] = (temp_array[1]*256 ) + temp_array[2]/4  ;
    temporary[1] = (temp_array[3]*256 )+ temp_array[4]/ 4  ;
    temporary[2]= temp_array[5];
    temporary[3]= temp_array[6];
    temporary[4]= temp_array[7];
    temporary[5]= temp_array[8];
    temporary[6]= temp_array[9];
    temporary[7]= temp_array[10];
}

     // i am returning fully decoded data array with pointer.
return temporary;
 }

最佳答案

不幸的是,这段代码还很幼稚,应该从头开始重写。

您应尽可能减少ISR,并且它不应包含任何应用程序逻辑。从UART接收数据后,ISR应该将数据放在缓冲区中。首选的方法是根本不使用中断,而是使用DMA。

如果您的MCU上没有DMA,则必须提出一种环形缓冲区结构,该结构将从ISR到应用程序充当FIFO。在读取期间,您需要某种保护方式,以确保读取时(竞争条件)ISR不会写入缓冲区。

由于UART通常很慢,因此,如果您从缓冲区中获取数据的代码比在UART上输入1 + 8 + 1位所需的时间更快,那么只需在读取期间禁用中断就足够了。

然后,最好使用最少的程序设计,将UART驱动程序与应用程序逻辑完全分开。

关于c - 通过Uart ISR更新变量而不中断分配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51182256/

10-12 21:34