
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将被不成功或不正确地发送,
//其实手册上说启用send位后会发送一个没用的帧,所以那个帧已经把这个发完了。
//当然,传输完成的标志位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 config(RCC _ HCLK _ div 1);
RCC _ pclk 1 config(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欧姆的匹配电阻的。









