请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
annQian 提问时间:2019-2-20 11:39 /
问题:在程序执行过程中 BuleToothParaTest   函数中所有已大红字体引用的函数必须打断点,否则程序运行异常,单步执行程序正常。能否帮忙解答一下
//结构体定义部分
typedef struct ParamSend
{
    uint8_t byte1;// 0x01  定值
    uint8_t byte2_readWriteFlag;//read :0x29  write :0x27
    uint8_t byte3;//0xfc  定值
    uint8_t byte4_dataLen;//这个字节以后总的数据长度
    uint8_t byte5_addrH;
    uint8_t byte6_addrL;  
    uint8_t  byte7_paramLen;
     /*以下字节是write 命令时需要的,read 不用管*/
    uint8_t  paramValue[16];
    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 :0x29  write :0x27
    uint8_t byte6;//0xfc  定值
    uint8_t byte7_succesFlag;//写命令 回复到这个字节
    /*以下两个字节是读命令时需要的*/
    uint8_t byte8_addrH;//把这个写成分开的,是发送和接收都不用缓存区了,直接使用结构体地址进行缓存即可
    uint8_t byte9_addrL;  
    uint8_t  byte10_paramLen;
    uint8_t  paramValue[16];//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,
};
//函数体部分
[url=]/**@content[/url]: 在配置模式下使用的函数 设置串口1的发送dma 和接收dma 通道号是固定的
**@arg TbufferAddr:发送缓冲区地址;TbufferAddr:发送长度;Tdatalen:接收缓冲区地址RbufferAddr :接收长度Rdatalen
**@arg dir :方向位  0:先发送后接收;  1:先接收后发送
**@return:no
**/
uint8_t  Usart_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;
    return  reValue;
}


[url=]/**@content[/url]: 发送缓冲区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);
}
[url=]/**@content[/url]: 发送缓冲区 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);
}
[url=]/**@content[/url]: 波特率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);
}
[url=]/**@content[/url]: 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;
}

[url=]/**@content[/url]: 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;   
}

[url=]/**@content[/url]: 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[0] = 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
      
       }
}

收藏 评论2 发布时间:2019-2-20 11:39

举报

2个回答
DavidTan 回答时间:2019-3-7 11:30:32
没见过在while(1)里不断把DMA初始化的用法,呵呵
annQian 回答时间:2019-3-11 08:30:06
问题已经解决了。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版