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

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个回答
tgw860910 回答时间:2019-3-7 11:30:32
没见过在while(1)里不断把DMA初始化的用法,呵呵
annqian 回答时间:2019-3-11 08:30:06
问题已经解决了。

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版