annqian 发表于 2019-2-20 11:39:11

STM32F103 串口收发使用DMA 程序没法全速运行的问题咨询

问题:在程序执行过程中 BuleToothParaTest   函数中所有已大红字体引用的函数必须打断点,否则程序运行异常,单步执行程序正常。能否帮忙解答一下
//结构体定义部分
typedef struct ParamSend
{
    uint8_t byte1;// 0x01定值
    uint8_t byte2_readWriteFlag;//read :0x29write :0x27
    uint8_t byte3;//0xfc定值
    uint8_t byte4_dataLen;//这个字节以后总的数据长度
    uint8_t byte5_addrH;
    uint8_t byte6_addrL;
    uint8_tbyte7_paramLen;
   /*以下字节是write 命令时需要的,read 不用管*/
    uint8_tparamValue;
    uint8_t actualLen;//实际发送的数据总长度
}ParamSendData, *pParamSendData;

typedef struct ParamRece
{
    uint8_t byte1;//0x04定值
    uint8_t byte2;//0x0e定值   
    uint8_t byte3_dataLen;//这个字节以后总的数据长度
    uint8_t byte4;//0x01定值
    uint8_t byte5;//read :0x29write :0x27
    uint8_t byte6;//0xfc定值
    uint8_t byte7_succesFlag;//写命令 回复到这个字节
    /*以下两个字节是读命令时需要的*/
    uint8_t byte8_addrH;//把这个写成分开的,是发送和接收都不用缓存区了,直接使用结构体地址进行缓存即可
    uint8_t byte9_addrL;
    uint8_tbyte10_paramLen;
    uint8_tparamValue;//read fail no this data
    uint8_t actualLen;//实际发送的数据总长度
}
ParamRece_Data, *pParamReceData;
//以下是变量定义部分
uint8_t blueTooth_Versionflag =0;//读取版本正确,这个标志位 置1
uint8_t paramReadFlag = 0;//配置模式下,读取蓝牙名称和写入的蓝牙名称一样paramReadFlag=1,不同为0
char * name="MC2sfc_TEST";//写入新的蓝牙名称
//配置模式下 发送缓存的结构体
ParamSendData SendParamData = {
    0x01,
    0x29,
};
//配置模式下 接收缓存的结构体
ParamRece_Data ReceParamData = {
    0x04,
    0x0e,
};
//函数体部分
/**@content: 在配置模式下使用的函数 设置串口1的发送dma 和接收dma 通道号是固定的
**@arg TbufferAddr:发送缓冲区地址;TbufferAddr:发送长度;Tdatalen:接收缓冲区地址RbufferAddr :接收长度Rdatalen
**@arg dir :方向位0:先发送后接收;1:先接收后发送
**@return:no
**/
uint8_tUsart_DmaBufferConfig(uint32_t TbufferAddr, uint16_t Tdatalen, uint32_t RbufferAddr, uint16_t Rdatalen)
{
    uint8_t reValue =0;
DMA_InitTypeDef Dma_init;
   
    DMA_Cmd(DMA1_Channel5, DISABLE); //disable rx 重新设置前 必须先禁止模块,不然计数器无法设置
    //rx
Dma_init.DMA_DIR = DMA_DIR_PeripheralSRC;
    Dma_init.DMA_Priority = DMA_Priority_Low ;
    Dma_init.DMA_BufferSize =Rdatalen ;
    Dma_init.DMA_MemoryBaseAddr = RbufferAddr;
    Dma_init.DMA_PeripheralBaseAddr =(uint32_t)&USART1->DR;   
Dma_init.DMA_M2M = DMA_M2M_Disable;
    Dma_init.DMA_Mode = DMA_Mode_Normal;
Dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
Dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
Dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    Dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //
    DMA_Init(DMA1_Channel5, &Dma_init);

    //tx
    DMA_Cmd(DMA1_Channel4, DISABLE); //disable tx重新设置前 必须先禁止模块,不然计数器无法设置   
    Dma_init.DMA_DIR = DMA_DIR_PeripheralDST;//从存储器读 发送 读存储器的数据到串口的DR reg 中
    Dma_init.DMA_Priority = DMA_Priority_Low;
    Dma_init.DMA_BufferSize =Tdatalen;
    Dma_init.DMA_MemoryBaseAddr = TbufferAddr;
    DMA_Init(DMA1_Channel4, &Dma_init);   
   
    DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);      
    USART_DMACmd(USART1,USART_DMAReq_Tx | USART_DMAReq_Rx,ENABLE); //使能串口1的DMA发送 接收
    DMA_Cmd(DMA1_Channel5, ENABLE); //enable rx
    DMA_Cmd(DMA1_Channel4, ENABLE); //enable tx
   
   
    while( !DMA_GetFlagStatus(DMA1_FLAG_TC5)){};
   
    DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_HT5 |DMA1_FLAG_TE5);
    DMA_ClearFlag(DMA1_FLAG_TC4 |DMA1_FLAG_GL4 |DMA1_FLAG_HT4);
   
    reValue =1;
    returnreValue;
}

/**@content: 发送缓冲区read配置函数,
**@arg paramLen :参数长度   ;startAddr:发送地址 ; SendData:发送缓冲区地址指针
**@return:no
**/
void McuReadConfigParam(uint8_t paramLen, uint16_t startAddr, pParamSendData SendData )
{
    SendData ->byte1 = 0x01;
    SendData ->byte2_readWriteFlag = 0x29;//dir=read
    SendData ->byte3 =0xFC;
    SendData ->byte4_dataLen = 3;
    SendData ->byte5_addrH = startAddr >> 8 & 0xFF;
    SendData ->byte6_addrL = startAddr & 0xFF;
    SendData ->byte7_paramLen = paramLen;   
    SendData -> actualLen = 7;
   
   // ParamSendDataConfig(SendData,&SendData -> actualLen, ReadBuffer);
}
/**@content: 发送缓冲区 write 配置函数,
**@arg paramLen :参数长度   ;startAddr:发送地址 ;paramValue :写入的数据SendData:发送缓冲区地址指针
**@return:no
**/
void McuWriteConfigParam( uint8_t paramLen, uint16_t startAddr, char * paramValue, pParamSendData SendData )
{
   uint8_t i=0;
   SendData -> byte1 = 0x01;
   SendData -> byte2_readWriteFlag = 0x27;//dir=write
   SendData -> byte3 =0xFC;
   SendData -> byte4_dataLen = 3 +paramLen;
   SendData -> byte5_addrH = startAddr >> 8 & 0xFF;
   SendData -> byte6_addrL = startAddr & 0xFF;
   SendData -> byte7_paramLen = paramLen;
   
   for(i=0;i< paramLen; i++)
      SendData -> paramValue = *(paramValue + i);
   
    SendData -> actualLen = 7 + paramLen;
   
   // ParamSendDataConfig(SendData,&SendData -> actualLen , ReadBuffer);
}
/**@content: 波特率115200 全双工 1位停止位,无校验位
**@arg no
**@return:no
**/
void usart1_init(void)
{
USART_InitTypeDef usart1_init;
usart1_init.USART_BaudRate =115200;
usart1_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usart1_init.USART_Mode= USART_Mode_Rx|USART_Mode_Tx;
usart1_init.USART_Parity =USART_Parity_No;
usart1_init.USART_StopBits = USART_StopBits_1;
usart1_init.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &usart1_init);   
    USART_Cmd(USART1, ENABLE);                  //使能串口1
   
    Gpio_Set_Do_TE(ST_GPIOA, 8, ST_DO_PP);//blue_tooth rst
    Gpio_Write_TE(ST_GPIOA, 8, 1);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
/**@content: Crc_Calc_SUM 计算这个dataAddr 开始的dataLen字节长度的校验和
**@arg no
**@return:no
**/
static uint16_t Crc_Calc_SUM(uint8_t *dataAddr, uint16_t dataLen)
{
    uint8_t tmp = 0;
uint16_t value = 0;
    uint16_t i = 0;
    for(i=GL_VAL_ZERO; i<dataLen; i++)
      tmp += dataAddr;
value = Type_U8_To_U16_TE(tmp);
    return value;
}

/**@content: BufferSetZero 设置buffer 地址 len 个地址的数据为0
**@arg no
**@return:no
**/
void BufferSetZero(uint8_t *buffer, uint8_t len)
{
    uint8_t i = 0;
    for(; i < len ; i++)
       *(buffer + i) = 0;   
}

/**@content: ChangeDmaLen 改变DMA发送或者接收 的字节长度
**@arg sentLen :USArt1 发送的字节长度; receLen :USArt1 接收的字节长度
**@return:no
**/
void ChangeDmaLen(uint8_t sentLen, uint8_t receLen)
{
    DMA_Cmd(DMA1_Channel4, DISABLE );//关闭USART1 TX DMA1 所指示的通道      
DMA_SetCurrDataCounter(DMA1_Channel4,sentLen);//DMA通道的DMA缓存的大小
   
    DMA_Cmd(DMA1_Channel5, DISABLE );//关闭USART1rX DMA1 所指示的通道      
DMA_SetCurrDataCounter(DMA1_Channel5,receLen);//DMA通道的DMA缓存的大小
   
DMA_Cmd(DMA1_Channel4, ENABLE);//使能USART1 TX DMA1 所指示的通道
    while( !DMA_GetFlagStatus(DMA1_FLAG_TC4)){};
   
DMA_Cmd(DMA1_Channel5, ENABLE);//使能USART1 rX DMA1 所指示的通道   
    DMA_ClearFlag(DMA1_FLAG_TC4 |DMA1_FLAG_GL4 |DMA1_FLAG_HT4);
    while( !DMA_GetFlagStatus(DMA1_FLAG_TC5)){};
    DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_HT5 |DMA1_FLAG_TE5);

}
// 验证,在main函数中
main()
{
    usart1_init();
    BuleToothParaTest()


}


void BuleToothParaTest(void)
{
    char * para = NULL;   
//    //read version 0xAF, 0x43, 0x6F, 0x6E,\\ 0x66, 0x69, 0x67, 0x05
    SendParamData.byte1 = 0xAF;
    SendParamData.byte2_readWriteFlag = 0x43;
    SendParamData.byte3 = 0x6f;
    SendParamData.byte4_dataLen = 0x6E;
    SendParamData.byte5_addrH = 0x66;
    SendParamData.byte6_addrL = 0x69;
    SendParamData.byte7_paramLen = 0x67;
    SendParamData.paramValue = 0x05;
    SendParamData.actualLen =8;
    ReceParamData.actualLen =8;
    while(! Usart_DmaBufferConfig((uint32_t)&SendParamData, SendParamData.actualLen, (uint32_t)&ReceParamData, ReceParamData.actualLen));
    if(Crc_Calc_SUM((uint8_t *)&ReceParamData, 7) ==ReceParamData.byte8_addrH)
    {
      if((ReceParamData.byte4 << 24 | ReceParamData.byte5 << 16 | ReceParamData.byte6 << 8 | ReceParamData.byte7_succesFlag) == 0x34303130)
         {
             blueTooth_Versionflag = 1;//blueTooth_Versionflag 版本正确的标志位                     
         }
    }
    //write1
   McuWriteConfigParam( 11, 0x000B, name, &SendParamData);         
   BufferSetZero((uint8_t *)&ReceParamData.byte1,26);//接收缓存区清0
   ChangeDmaLen(7+11, 7);//开始 写
   
   //read1
   McuReadConfigParam(16, 0x000B, &SendParamData);   
   BufferSetZero((uint8_t *)&ReceParamData.paramValue,16);//接收缓存区清0
   ChangeDmaLen(7, 10+11);
   
   if(ReceParamData.byte7_succesFlag ==0)
    {
      para =(uint8_t *) &ReceParamData.paramValue;
    }
    if(strcmp(name,para) == 0)
       {
            McuWriteConfigParam( 11, 0x000B, name, &SendParamData);
         
            BufferSetZero((uint8_t *)&ReceParamData.byte1,26);//接收缓存区清0
            ChangeDmaLen(7+11, 7);//开始 写
             if(ReceParamData.byte7_succesFlag ==0)
            {
               BufferSetZero((uint8_t *)&ReceParamData.paramValue,26);//接收缓存区清0
               McuReadConfigParam(11, 0x000B, &SendParamData);
               ChangeDmaLen(7, 10+11);//开始 read
                  if(ReceParamData.byte7_succesFlag ==0)
                {
                  if(strcmp(name,para) == 0)
                         paramReadFlag = 1;//write new name success
                }
            }
       }else
       {
      //reset
      
       }
}

tgw860910 发表于 2019-3-7 11:30:32

没见过在while(1)里不断把DMA初始化的用法,呵呵

annqian 发表于 2019-3-11 08:30:06

问题已经解决了。
页: [1]
查看完整版本: STM32F103 串口收发使用DMA 程序没法全速运行的问题咨询