1.首先我说明一下,我这次用的STM32芯片是STM32F103RB,我用的资源是芯片上的USART1。
2.以下是我的电路图:
注:电路稍加修改可以更好。在B点和A点分别将下拉电阻接地,上拉电阻接5v,电阻值可以选择10K。这是为了确保在没有数据传输时确定两条数据线的状态。
做个简单的解释:
(1)PA8是sp3485的发送/接收使能端,只能支持半双工通信,所以这个管脚用来控制芯片是接收还是发送数据。
(2)在一些电路连接中,sp3485的A端和B端中的一个会用一个上拉电阻连接到3.3V,另一个会用一个下拉电阻连接到GND,这样当这个sp3485不参与通信时,网络的稳定性不会受到影响。
3.这种调试模式
PC ——USB转232转换器——RS232/RS485双向转换器——sp3485——STM32,因为是第一次调试sp3485芯片,当然没太在意。让我先用电脑调试一下。
调试后,我们会看到板与板之间的通信。
4.该测试的代码:
主要功能:
intmain(void)
{
RCC _ Configuration();
NVIC _配置();
GPIO _ Configuration();
USART _ Configuration();
GPIO_SetBits(GPIOA,GPIO _ Pin _ 8);//PA8是sp3485的收发控制端,这里设置为先发(实现的功能是STM32上电后先发一个4和一个3给PC)。
delay _ ms(2);//等一下,查一下sp3485的手册找原因。
USART_ClearFlag(USART1,USART _ FLAG _ TC);//这句话很关键。没有这句话,这4就发不成功或者发错了。
//其实手册上说启用发送位会发一个没用的帧,所以那个帧就发了这个。
//当然设置了传输完成的标志位USART_FLAG_TC。
USART_SendData(USART1,4);
while(USART _ GetFlagStatus(USART 1,USART _ FLAG _ TC)==RESET);//如果发送完成标志位清零,可以等待发送完成标志位置位,判断帧是否已经发出。
USART_SendData(USART1,3);
while(USART _ GetFlagStatus(USART 1,USART _ FLAG _ TC)==RESET);
while(1)
{
GPIO_ResetBits(GPIOA,GPIO _ Pin _ 8);//现在复位PA8,尝试接收PC发送的数据。
delay _ ms(2);//等一下,查一下sp3485的手册找原因。
USART_ClearFlag(USART1,USART _ FLAG _ rx ne);//由于发送完成标志位在上面发送之前清零,所以这里把接收完成标志位清零是一个好习惯。
while(1)
{
If (usart _ getflagstatus (usart1,usart _ flag _ rxne)==set)//判断是否接收到一帧数据。
{
buf[j]=USART _ receive data(USART 1);//如果收到,直接放在缓冲区。
}
If(10==j)//接收10后,跳出并停止接收。有意义就OK。
打破;
}
j=0;//清除J变量,使实验可以重复接收PC发送的10个数据。
GPIO_SetBits(GPIOA,GPIO _ Pin _ 8);//设置sp3485发送数据。
while(USART _ GetFlagStatus(USART 1,USART _ FLAG _ TC)==RESET);
delay _ ms(2);//等一下,查一下sp3485的手册找原因。
for(I=0;i10我)
{
USART_SendData(USART1,buf[I]);//依次将数据发送出去。
while(USART _ GetFlagStatus(USART 1,USART _ FLAG _ TC)==RESET);
}
}
}
注意:使用STM32的串口进行485通信时,发送数据时,检测到上一次数据传输后的标志位已经置位,但485芯片的发送引脚不能立即禁用,因为虽然标志位已经置位,但485芯片的数据还没有完全发送出去,此时需要ms级别的延迟,2毫秒左右基本没问题。
RCC设置功能:
voidRCC_Configuration(无效)
{
RCC _ DeInit();
RCC _ HSE config(RCC _ HSE _ ON);
HSEStartUpStatus=RCC _ WaitForHSEStartUp();
if(HSEStartUpStatus==SUCCESS)
{
RCC _ HCLKConfig(RCC _ SYSCLK _ div 1);
rcc _ pclk 2配置(RCC _ hclk _ div 1);
rcc _ pclk 1配置(RCC _ hclk _ div 2);
flash _ set延迟(flash _ latency _ 2):
FLASH_PrefetchBuffer_Enable:
/*PLLCLK=8MHz*9=72MHz*/
RCC _ pllconfig(RCC _ PLL source _ HSE _ div 1、RCC _ pllm _ 9);
RCC_PLLCmd(启用):
while(RCC _ getflag状态)(RCC _ flag _ PLL rdy)=1重置
{
}
RCC _ sys lk config(RCC _ sys LCS source _ PLL clk):
while(RCC _ getsy cksource()!=0x08)
{
}
}
RCC _ APB 2 peri CK cmd(RCC _ APB 2 peri _ usrt 1 | RCC _ APB 2 peri _ gp IOA | RCC _ APB 2 peri _ gp IOC,启用);
}
通用输入输出接口(消歧义)设置函数:
S7-1200可编程控制器
{
gpio _ inittype定义gpio _ init结构:
GPIO_InitStructure .GPIO_Pin=GPIO_Pin_9:
GPIO_InitStructure .GPIO_Mode=GPIO_Mode_AF_PP:
GPIO_InitStructure .GPIO_Speed=GPIO_Speed_50MHz:
gpio _ init(gpio,GPIO_InitStructure):
GPIO_InitStructure .GPIO_Pin=GPIO_Pin_10:
GPIO_InitStructure .gpio _ mode=gpio _ mode _ in _ floating;
gpio _ init(gpio,GPIO_InitStructure):
GPIO_InitStructure .GPIO_Pin=GPIO_Pin_8:
GPIO_InitStructure .GPIO _ Mode=GPIO _ Mode _ Out _ PP://GPIO _ Mode _ Out _ PP=0x 10
GPIO_InitStructure .GPIO_Speed=GPIO_Speed_50MHz:
gpio _ init(gpio,GPIO_InitStructure):
GPIO_InitStructure .GPIO_Pin=GPIO_Pin_8:
GPIO_InitStructure .GPIO _ Mode=GPIO _ Mode _ Out _ PP://GPIO _ Mode _ Out _ PP=0x 10
GPIO_InitStructure .GPIO_Speed=GPIO_Speed_50MHz:
gpio _ init(gpio,GPIO_InitStructure):
}
乌瑟特设置函数:
voidUSART_Configuration(请参阅)
{
usert _ inittype defusrt _ init结构:
usrt _ clockitstypedefusrt _ clockinitstructure:
usart _结构usart _ clock=usart _ clock _ disable
usart _结构usart _ cpol=usart _ cpol _ low:
usart _时钟结构使用类型_时钟结构usart _ cpha=usart _ cpha _ 2 edge:
usart _时钟结构使用类型_时钟结构usrt _ load it=usrt _ load it _ disable:
usrt _ ckinit(usrt 1,usart _ clockinitstructure):
usart _ initstructure .S7-1200可编程控制器:
usart _ initstructure .usrt _字长=usrt _字长_ 8b:
usart _ initstructure .usart _ stopbits=usart _ stopbits _ 1:
usart _ initstructure .usart _ parity=usart _ parity _ no:
usart _ initstructure .usrt _硬件低电平控制=usrt _硬件低电平控制_无:
usart _ initstructure .usrt _ mode=usrt _ mode _ rx | usrt _ mode _ tx;
usrt _ init(usrt 1、usart _ initstructure):
usrt _ cmd(usrt 1,启用):
}
不知道。北卡罗来纳州设置函数:
voidNVIC_Configuration(请参阅)
{
#ifdefvect _ tab _ ram
NVC _集向量表(NVC _ vectab _ ram,0x 0);
# else
NVC _集向量表(NVC _ vectab _ flash,0x 0);
#endif
}
5.实验结果
不成功,找了很久的原因,首先请检查sp3485与第232/485号决议双向转换头的连接线,我得到的最终的正确的连接办法是sp3485的一个a连接到T/R,而sp3485的乙。非政府组织连接到S7-1200可编程控制器。
更改连接顺序之后还是出现了很奇怪的现象,每次上电之后个人电脑的串口调试助手都会接收到03:00时,都要多一个00(十六进制),还有更奇怪的现象,当在个人电脑机上输入十个数据,点击发送之后,返回来居然是20个数据,前10个数据是错误的,后10个才是我发送过去的数据-我.
这个现象非常奇怪,将程序反复修改,还是不能解决问题,甚至一度怀疑sp3485坏掉了,最后弄了一整天,将sp3485A和乙。非政府组织引脚之间的120欧姆的电阻去掉,一切恢复正常了!
说明一下:我的sp3485和第232/485号决议互转器之间的距离20厘米(20厘米)左右,所以这个距离应该是不用接120欧姆的匹配电阻的。
标签:SP3485芯片STM32