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

紧急求助,关于STM32F407VGT6芯片USART串口通讯(sp3232)问题...

[复制链接]
annysky 提问时间:2019-8-5 13:28 /
悬赏15ST金币未解决
今天在这里请教大家一个问题,关于STM32F407的串口通讯的问题,其实这是个很LOW的问题,但是不得不请教大家。
1.问题描述
使用的单片机是STM32F407VGT6芯片,100引脚的。串口通道到USART3,串口芯片是SP3232芯片。通讯速率是115200-8-n-1。
对单片机进行测试时,发现收发的数据出现乱码的情况,完全不能使用。


2.故障排查
(1)首先检查硬件问题。
硬件电路图如下:

该电路图按照数据手册还有原子哥的电路图进行设计的,测试各点电压:(16脚电压3.27V,2脚电压5.89V,6脚电压-5.3V,1脚与3脚之间电压2.9V,4脚与5脚之间电压5.56V)。
外部通过USB转TTL工具将单片机与PC连接起来,进行了交叉连接。


(2)检查调试工具
其中怀疑是调试工具的问题,换了3个不同厂家的USB转TTL的进行测试,显示的结果都是一样,通讯乱码。排除通信工具的问题。


(3)检查串口助手
同样换了3个串口调试助手,包括原子的串口助手,问题现象也是一样。


(4)检查通讯芯片
a.鉴于网上以及自己经验,SP2332的假货比较多,对测试的SP3232进行更换新的,在此期间更换为MAX232(将芯片的电压通过飞线更改为5V),又通过正规渠道更换为max3232,同样的结果,通讯乱码。
b.对SP3232进行回环测试,即将USART3(9脚和10脚短接),通过串口调试助手发送数据,此时发送数据正常。又将USART6(11脚和12脚)短接,发送数据也正常,说明通讯芯片是正常的。


(5)检测单片机的通讯引脚
测试方法为,将SP3232芯片去掉,将USART3的TXD和RXD直接与USB转TTL的工具的RXD和TXD连接,通过调试助手发送数据,也能正常收发数据,发送什么回复什么数据。
这时将SP3232芯片重新焊接上,通讯还是乱码,简直无法相信。


(6)检查单片机外围元器件
a.首先检查有无虚焊问题。
将单片机外围的元器件重新焊锡,补焊
b.检查电路问题,对照官方的原理图以及网上关于STM32F407VGT6芯片的原理图进行仔细核实,没有发现什么问题。
原理图如下(关于电源和晶振部分):



c.检查晶振
晶振为8MHz,焊接并无问题,测试晶振引脚电压,分别为1.81V、1.69V。
并将晶振Y3(32.768KHz)去掉。

(7)检查程序问题
本次测试实例有两个,一个是原子哥的《实验4 串口实验》,另外一个是野火的《USART2—USART2接发》,不要见怪,实在没办法。
a.原子哥的《实验4 串口实验》
修改引脚和时钟、中断配置:


//重定义fputc函数
int fputc(int ch, FILE *f)
{         
        while((USART3->SR&0X40)==0);//循环发送,直到发送完毕   
        USART3->DR = (u8) ch;      
        return ch;
}
#endif

#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误           
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,        接收完成标志
//bit14,        接收到0x0d
//bit13~0,        接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记        


//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound){
   //GPIO端口设置
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //使能GPIOA时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART1时钟

        //串口1对应引脚复用映射
        GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_USART3); //GPIOA9复用为USART1
        GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_USART3); //GPIOA10复用为USART1
        
        //USART1端口配置
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; //GPIOA9与GPIOA10
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //速度50MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
        GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化PA9,PA10


   //USART1 初始化设置
        USART_InitStructure.USART_BaudRate = bound;//波特率设置
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式
        USART_Init(USART3, &USART_InitStructure); //初始化串口1
        
        USART_Cmd(USART3, ENABLE);  //使能串口1
        
        USART_ClearFlag(USART3, USART_FLAG_TC);
        
#if EN_USART1_RX        
        USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启相关中断


        //Usart1 NVIC 配置
        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//串口1中断通道
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;                //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器、


#endif
        
}




void USART3_IRQHandler(void)                        //串口1中断服务程序
{
        u8 Res;
#ifdef OS_TICKS_PER_SEC                 //如果时钟节拍数定义了,说明要使用ucosII了.
        OSIntEnter();   
#endif
        if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
        {
                Res =USART_ReceiveData(USART3);//(USART1->DR);        //读取接收到的数据
               
                if((USART_RX_STA&0x8000)==0)//接收未完成
                {
                        if(USART_RX_STA&0x4000)//接收到了0x0d
                        {
                                if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                else USART_RX_STA|=0x8000;        //接收完成了
                        }
                        else //还没收到0X0D
                        {        
                                if(Res==0x0d)USART_RX_STA|=0x4000;
                                else
                                {
                                        USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                                        USART_RX_STA++;
                                        if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收         
                                }                 
                        }
                }                    
  }
#ifdef OS_TICKS_PER_SEC                 //如果时钟节拍数定义了,说明要使用ucosII了.
        OSIntExit();                                                                                          
#endif
}



在主函数中进行修改后:
        while(1)
        {
                if(USART_RX_STA&0x8000)
                {                                          
                        len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
                        printf("\r\n您发送的消息为:\r\n");
                        for(t=0;t<len;t++)
                        {
                                USART_SendData(USART3, USART_RX_BUF[t]);         //向串口1发送数据
                                while(USART_GetFlagStatus(USART3,USART_FLAG_TC)!=SET);//等待发送结束
                        }
                        printf("\r\n\r\n");//插入换行
                        USART_RX_STA=0;
                }else
                {
                        times++;
                        if(times%5000==0)
                        {
                                printf("\r\nALIENTEK 探索者STM32F407开发板 串口实验\r\n");
                                printf("正点原子@ALIENTEK\r\n\r\n\r\n");
                        }
                        if(times%200==0)printf("52353535\r\n");  
                        if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
                        delay_ms(10);   
                }
        }



查看时钟配置:
#if !defined  (HSE_VALUE)
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
  
#endif /* HSE_VALUE */



#if defined (STM32F40_41xxx)
  uint32_t SystemCoreClock = 168000000;
#endif /* STM32F40_41xxx */



/************************* PLL Parameters *************************************/
#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M   



仿真查看USART3的配置情况:

与数据手册进行对比查看,没有发现什么问题。


b.野火的《USART2—USART2接发》


//引脚定义
/*******************************************************/
#define RS232_USART                                     USART3
#define RS232_USART_CLK                              RCC_APB1Periph_USART3


#define RS232_USART_RX_GPIO_PORT                GPIOD
#define RS232_USART_RX_GPIO_CLK                 RCC_AHB1Periph_GPIOD
#define RS232_USART_RX_PIN                          GPIO_Pin_9
#define RS232_USART_RX_AF                           GPIO_AF_USART3
#define RS232_USART_RX_SOURCE                   GPIO_PinSource9


#define RS232_USART_TX_GPIO_PORT               GPIOD
#define RS232_USART_TX_GPIO_CLK                 RCC_AHB1Periph_GPIOD
#define RS232_USART_TX_PIN                          GPIO_Pin_8
#define RS232_USART_TX_AF                           GPIO_AF_USART3
#define RS232_USART_TX_SOURCE                   GPIO_PinSource8

#define RS232_USART_IRQHandler                   USART3_IRQHandler
#define RS232_USART_IRQ                              USART3_IRQn
/************************************************************/
//串口波特率
#define RS232_USART_BAUDRATE                    115200





/**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = RS232_USART_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
}




/**
  * @brief  RS232_USART GPIO 配置,工作模式配置。115200 8-N-1 ,中断接收模式
  * @param  无
  * @retval 无
  */
void Debug_USART_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
               
  RCC_AHB1PeriphClockCmd( RS232_USART_RX_GPIO_CLK|RS232_USART_TX_GPIO_CLK, ENABLE);


  /* 使能 UART 时钟 */
  RCC_APB1PeriphClockCmd(RS232_USART_CLK, ENABLE);
  
  /* 连接 PXx 到 USARTx_Tx*/
  GPIO_PinAFConfig(RS232_USART_RX_GPIO_PORT,RS232_USART_RX_SOURCE, RS232_USART_RX_AF);


  /*  连接 PXx 到 USARTx__Rx*/
  GPIO_PinAFConfig(RS232_USART_TX_GPIO_PORT,RS232_USART_TX_SOURCE,RS232_USART_TX_AF);


  /* 配置Tx引脚为复用功能  */
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;


  GPIO_InitStructure.GPIO_Pin = RS232_USART_TX_PIN  ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(RS232_USART_TX_GPIO_PORT, &GPIO_InitStructure);


  /* 配置Rx引脚为复用功能 */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pin = RS232_USART_RX_PIN;
  GPIO_Init(RS232_USART_RX_GPIO_PORT, &GPIO_InitStructure);
                        
  /* 配置串口RS232_USART 模式 */
  USART_InitStructure.USART_BaudRate = RS232_USART_BAUDRATE;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No ;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(RS232_USART, &USART_InitStructure);
        
        NVIC_Configuration();
        /*配置串口接收中断*/
        USART_ITConfig(RS232_USART, USART_IT_RXNE, ENABLE);
        
  USART_Cmd(RS232_USART, ENABLE);
}



//中断接收函数
extern uint8_t Rxflag;
extern uint8_t ucTemp;
void RS232_USART_IRQHandler(void)
{
        if(USART_GetITStatus( RS232_USART, USART_IT_RXNE ) != RESET)
        {               
          Rxflag=1;               
                ucTemp = USART_ReceiveData( RS232_USART );
        }         
}

主函数:
  while(1)
        {        
                /*
                        接收DEBUG_USART口的数据,分析并处理
                        可以将此段代码封装为一个函数,在主程序其它流程调用
                */
                if(Rxflag)
                {
                        if (usRxCount < sizeof(ucaRxBuf))
                        {
                                ucaRxBuf[usRxCount++] = ucTemp;
                        }
                        else
                        {
                                usRxCount = 0;
                        }
                        
                        /* 简单的通信协议,遇到回车换行符认为1个命令帧,可自行加其它判断实现自定义命令 */
                        /* 遇到换行字符,认为接收到一个命令 */
                        if (ucTemp == 0x0A)        /* 换行字符 */
                        {               
                                /*检测到有回车字符就把数据返回给上位机*/
                                Usart_SendStr_length( RS232_USART, ucaRxBuf, usRxCount );
                                //Usart_SendString();
                                usRxCount = 0;
                        }
                        Rxflag=0;      
                }
        }

同样的将系统的时钟更改为8MHz,进行测试。

3.查找资料
针对网上说的各种方法,比如文件属性,只读更改为可修改;比如系统时钟的分频,将系统的总时钟更改为72Mhz测试,均以失败而告终。

4.紧急求助
实在没有办法了,希望各位看到此贴的朋友,还有哪些我还没有注意到的,希望给一点建议,非常感谢。

收藏 评论16 发布时间:2019-8-5 13:28

举报

16个回答
annysky 最优答案 回答时间:2019-8-9 10:18:29
wu18946796976 发表于 2019-8-8 19:41
问题解决没有  应该是波特率的问题  你可以设置单片机波特率为9600  把串口的波特率换一下试试  4800 14400 ...

问题已经解决,使用RS232时使用USB转232调试工具,通讯正常啦。真是血的教训。单片机接SP3232后,转化成了232电平,而我使用的工具是USB转TTL的(PL2303)测试工具,所以测试测试都是乱码。说白了电平不兼容。大家以后也要切记。还是我自己没有弄清楚。
mmuuss586 回答时间:2019-8-6 09:49:36
可能232芯片问题吧;
波特率低些是不是就可以了?
这个芯片以前用过,开了6个串口,都是115200波特率都没问题;
mmuuss586 回答时间:2019-8-6 09:49:52
用示波器看下波形看看;
annysky 回答时间:2019-8-6 14:29:48
mmuuss586 发表于 2019-8-6 09:49
可能232芯片问题吧;
波特率低些是不是就可以了?
这个芯片以前用过,开了6个串口,都是115200波特率都没问 ...

断开MCU与232接口片的连接,短接232接口片的TTL侧收发引脚,然后用PC的RS232接口测试,波特率设置与MCU相同,数据无误。所以232接口片没问题
annysky 回答时间:2019-8-6 14:30:05
mmuuss586 发表于 2019-8-6 09:49
用示波器看下波形看看;

正准备测试看看到底什么问题
天臆弄人 回答时间:2019-8-7 09:11:52
串口简单啊,要么芯片,要么电源,看你这描述 电源供电问题。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

annysky 回答时间:2019-8-7 10:42:27
天臆弄人 发表于 2019-8-7 09:11
串口简单啊,要么芯片,要么电源,看你这描述 电源供电问题。

芯片电源供电是3.3V呀,没有毛病呢
天臆弄人 回答时间:2019-8-7 14:25:34
annysky 发表于 2019-8-7 10:42
芯片电源供电是3.3V呀,没有毛病呢

maX3232,
天臆弄人 回答时间:2019-8-7 14:29:58
不只是电源的还是4个电容呢,先稳压住外部电源,加些10uf电容,
相当初新手刚搞串口时候,遇到比你还多,还奇芭的问题,
lwg8458 回答时间:2019-8-8 09:09:35
别是串口助手ASCII与HEX显示没切换哦
12下一页

所属标签

相似问题

官网相关资源

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