[STM32F1] STM32调试sp3485技术总结

[复制链接]
 楼主| 发表于 2016-8-15 16:04 | 显示全部楼层 |阅读模式
1.首先说明一下本人这次使用的STM32芯片是STM32F103RB,使用的资源是片内的USART1。
2.下面是我的电路连接图:


做一下简单的说明:
(1)PA8是sp3485的发送/接收使能端,sp3485只能支持半双工的通信,所以这个引脚就是来控制这个芯片到底是收数据还是发数据的。
(2)在有些电路连接中,sp3485的A和B端会一个被连接一个上拉电阻到3.3V,另一个会连接一个下拉电阻到GND,这样做的目的是当本sp3485不参与通信时不会影响网络的稳定性。
3.本次调试方式
PC机——USB转232转换头——RS232/RS485双向转换头——sp3485——STM32,因为是第一次调试sp3485芯片,所以当然没有太大意,先拿电脑调试,调试通了再看板子和板子之间的通信了。
 楼主| 发表于 2016-8-15 16:05 | 显示全部楼层
4.本次试验的代码:
main函数:
  1. int main(void)
  2. {
  3.     /* Configure the system clocks */
  4.     RCC_Configuration();
  5.      
  6.     /* NVIC Configuration */
  7.     NVIC_Configuration();
  8.     /* Configure the GPIOs */
  9.     GPIO_Configuration();

  10.     /* Configure the USART1 */
  11.     USART_Configuration();
  12.     GPIO_SetBits(GPIOA, GPIO_Pin_8);  //PA8是sp3485发送/接收控制端,这里先设置为发送(实现的功能就是上电之后STM32先向PC发送一个4和一个3)
  13.     delay_ms(2);//稍稍延时一下,原因去查看sp3485的手册吧
  14.     USART_ClearFlag(USART1,USART_FLAG_TC);//这一句很关键,如果没有这一句这个4会发送不成功或者发送错误的,
  15.                                                                                            //其实手册上讲了使能发送位后会发送一个无用的帧,所以那个帧发送完了这个
  16.                                                                                            //发送完成的标志位USART_FLAG_TC当然也被置位了。
  17.     USART_SendData(USART1, 4);
  18.     while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);//上面清除了发送完成标志位,那么这里就可以等待发送完成标志位被置位来判断这一帧是否发完了
  19.     USART_SendData(USART1, 3);
  20.     while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
  21.     while(1)
  22.     {
  23.        GPIO_ResetBits(GPIOA, GPIO_Pin_8);//现在把PA8清零,试试接收PC机发送过来的数据
  24.        delay_ms(2);//稍稍延时一下,原因去查看sp3485的手册吧
  25.        USART_ClearFlag(USART1,USART_FLAG_RXNE);//既然上面开始发送之前都将发送完成标志位清零,这里也将接收完成标志位清下零,就当是一个好习惯吧
  26.        while(1)
  27.       {
  28.           if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)//判断是否有一帧数据接收完成
  29.           {           
  30.                buf[j++] = USART_ReceiveData(USART1); //接收完成的话就直接放到缓存区域里  
  31.           }
  32.          if(10 == j)//接收完成10个之后就跳出去,不再接收了,有个意思就OK了
  33.          break;
  34.       }
  35.     j = 0;//清零一下j变量,使得实验可以反复接收PC发过来的10个数据
  36.    GPIO_SetBits(GPIOA, GPIO_Pin_8);//将sp3485设置为发送数据
  37.     while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
  38.    delay_ms(2);//稍稍延时一下,原因去查看sp3485的手册吧
  39.     for(i = 0; i < 10; i++)
  40.    {
  41.         USART_SendData(USART1, buf[i]);//将数据依次发送出去
  42.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
  43.     }
  44. }
  45. }


 楼主| 发表于 2016-8-15 16:06 | 显示全部楼层
RCC设置函数:
  1. void RCC_Configuration(void)
  2. {
  3.   /* RCC system reset(for debug purpose) */
  4.   RCC_DeInit();
  5.   /* Enable HSE */
  6.   RCC_HSEConfig(RCC_HSE_ON);
  7.   /* Wait till HSE is ready */
  8.   HSEStartUpStatus = RCC_WaitForHSEStartUp();
  9.   if(HSEStartUpStatus == SUCCESS)
  10.   {
  11.     /* HCLK = SYSCLK */
  12.     RCC_HCLKConfig(RCC_SYSCLK_Div1);

  13.     /* PCLK2 = HCLK */
  14.     RCC_PCLK2Config(RCC_HCLK_Div1);
  15.     /* PCLK1 = HCLK/2 */
  16.     RCC_PCLK1Config(RCC_HCLK_Div2);
  17.     /* Flash 2 wait state */
  18.     FLASH_SetLatency(FLASH_Latency_2);
  19.     /* Enable Prefetch Buffer */
  20.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  21.     /* PLLCLK = 8MHz * 9 = 72 MHz */
  22.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
  23.     /* Enable PLL */
  24.     RCC_PLLCmd(ENABLE);
  25.     /* Wait till PLL is ready */
  26.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
  27.     {
  28.     }
  29.     /* Select PLL as system clock source */
  30.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  31.     /* Wait till PLL is used as system clock source */
  32.     while(RCC_GetSYSCLKSource() != 0x08)
  33.     {
  34.     }
  35.   }
  36.   
  37.   /* Enable USART1 and GPIOA clock */
  38.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
  39. }


 楼主| 发表于 2016-8-15 16:06 | 显示全部楼层
GPIO设置函数:
  1. void GPIO_Configuration(void)
  2. {
  3.   GPIO_InitTypeDef GPIO_InitStructure;
  4.   /* Configure USART1 Tx (PA.09) as alternate function push-pull */
  5.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  6.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  7.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  8.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  9.    
  10.   /* Configure USART1 Rx (PA.10) as input floating */
  11.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  12.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  13.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  14. /* Configure PC. as Output push-pull */
  15. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  16. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//GPIO_Mode_Out_PP = 0x10
  17. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  18. GPIO_Init(GPIOA, &GPIO_InitStructure);
  19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  20. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//GPIO_Mode_Out_PP = 0x10
  21. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  22. GPIO_Init(GPIOC, &GPIO_InitStructure);
  23. }
USART设置函数:
  1. void USART_Configuration(void)
  2. {
  3.   USART_InitTypeDef USART_InitStructure;
  4.   USART_ClockInitTypeDef  USART_ClockInitStructure;
  5. USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
  6. USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
  7. USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
  8. USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
  9. /* Configure the USART1 synchronous paramters */
  10. USART_ClockInit(USART1, &USART_ClockInitStructure);
  11. USART_InitStructure.USART_BaudRate = 9600;
  12. USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  13. USART_InitStructure.USART_StopBits = USART_StopBits_1;
  14. USART_InitStructure.USART_Parity = USART_Parity_No ;
  15. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  16. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  17. /* Configure USART1 basic and asynchronous paramters */
  18. USART_Init(USART1, &USART_InitStructure);
  19.    
  20.   /* Enable USART1 */
  21. USART_Cmd(USART1, ENABLE);
  22. }


 楼主| 发表于 2016-8-15 16:08 | 显示全部楼层
NVIC设置函数:
  1. void NVIC_Configuration(void)
  2. {
  3. #ifdef  VECT_TAB_RAM
  4.   /* Set the Vector Table base location at 0x20000000 */
  5.   NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
  6. #else  /* VECT_TAB_FLASH  */
  7.   /* Set the Vector Table base location at 0x08000000 */
  8.   NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);  
  9. #endif
  10. }
5.实验结果
不成功,找了很久的原因,首先请检查sp3485与232/485双向转换头的连接线,我得到的最终的正确的连接办法是sp3485的A连接到T/R+,而sp3485的B连接到T/R-。
更改连接顺序之后还是出现了很奇怪的现象,每次上电之后PC的串口调试助手都会接收到04 03 00,都要多一个00(十六进制),还有更奇怪的现象,当在PC机上输入十个数据,点击发送之后,返回来居然是20个数据,前10个数据是错误的,后10个才是我发送过去的数据。。。
这个现象非常奇怪,将程序反复修改,还是不能解决问题,甚至一度怀疑sp3485坏掉了,最后弄了一整天,将sp3485A和B引脚之间的120欧姆的电阻去掉,一切恢复正常了!
说明一下:我的sp3485和232/485互转器之间的距离20cm左右,所以这个距离应该是不用接120欧姆的匹配电阻的。
发表于 2016-8-15 17:29 | 显示全部楼层
谢谢分享;
发表于 2016-8-16 08:43 | 显示全部楼层
energyplants 发表于 2016-8-15 16:08
NVIC设置函数:5.实验结果
不成功,找了很久的原因,首先请检查sp3485与232/485双向转换头的连接线,我得到 ...

注意一下,485芯片 接收状态切换到发送状态需要多久之间才能稳定
发表于 2016-8-16 09:24 | 显示全部楼层
A上拉,B下拉不要忽视
发表于 2016-8-16 15:00 | 显示全部楼层
jeraw 发表于 2016-8-16 09:24
A上拉,B下拉不要忽视

这个是必须的吗?该如何接入电阻?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

123

帖子

2

粉丝
快速回复 返回顶部 返回列表