赞
踩
准备工作 首先我们需要准备的工具是一根USB-485转接数据线,STM32F103单片机,也可以是其他单片机,思想思路类似。两根公对公杜邦线,为了让板子和转接口连接。
连线工作本人用的485转接器是T/R-接F103单片机B端,T/R+接单片机A端。使用跳线帽将PA2和48R连接,PA3和48T连接。然后连接好串口数据线即可。
程序部分我们使用的是串口2,所以一定要先初始化串口2.
//初始化IO 串口2 //pclk1:PCLK1时钟频率(Mhz) //bound:波特率 void RS485_Init(u32 bound) //串口2定义函数 { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);//使能GPIOA,D时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PD7端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出--一定要设置为推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置速率为50hz GPIO_Init(GPIOD, &GPIO_InitStructure); //这个口和硬件的连接有关系,一般不要改,正点原子的485在串口2 /* 正点原子的串口2离485RX,485TX最近,所以下面我们初始化串口2 ,让串口2使用跳线帽去连接485RX,TX. */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2 RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位 #ifdef EN_USART2_RX //如果使能了接收 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(USART2, &USART_InitStructure); ; //初始化串口 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级2级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断 USART_Cmd(USART2, ENABLE); //使能串口 #endif RS485_TX_EN=0; //默认为接收模式 }
接下来继续配置串口中断
#ifdef EN_USART2_RX //如果使能了接收 //接收缓存区 u8 RS485_RX_BUF[64]; //接收缓冲,最大64个字节. //接收到的数据长度 u8 RS485_RX_CNT=0; void USART2_IRQHandler(void)//串口中断函数 { u8 res; //设置一个串口数据接收变量 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //假设接收到数据 { res =USART_ReceiveData(USART2); //读取接收到的数据,将接收到的数据赋值给res变量 if(RS485_RX_CNT<64) //如果接收的数据长度小于64,此时认定为没有接收完 { RS485_RX_BUF[RS485_RX_CNT]=res; //记录接收到的值 RS485_RX_CNT++; //接收数据增加1 } } } #endif
此时基本的串口已经配置结束,需要继续使用接收和发送。
//RS485发送len个字节. //buf:发送区首地址 //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节) void RS485_Send_Data(u8 *buf,u8 len) { u8 t; RS485_TX_EN=1; //设置为发送模式 for(t=0;t<len;t++) //循环发送数据 { while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //等待发送完成,USART_FLAG_TC发送完成标志,置位时表示发送完成 USART_SendData(USART2,buf[t]); } while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); RS485_RX_CNT=0; RS485_TX_EN=0; //设置为接收模式 }
//RS485查询接收到的数据 //buf:接收缓存首地址 //len:读到的数据长度 void RS485_Receive_Data(u8 *buf,u8 *len)//数组通过首地址来读取,len是一个指针,*len表示这个指针所代表的值,传入后可以对参数修改 { u8 rxlen=RS485_RX_CNT;//CNT的值在中断服务函数里,表示收到的数据个数,这个时候,数据已经在中断RS485_RX_BUF[]存储上了 u8 i=0; *len=0; //默认为0 delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束 if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了 { for(i=0;i<rxlen;i++) { buf[i]=RS485_RX_BUF[i]; //将中断函数中的缓存按位发到buf[i] } *len=RS485_RX_CNT; //记录本次数据长度 RS485_RX_CNT=0; //清零 } }
此时整个串口就可以使用了,我们只需要在主函数调用即可收发了。
//测试========
【当PC的串口助手为主机,F103为从机】
实现功能:PC串口助手发送------F103屏幕显示。
我们采用串口助手,波特率和代码必须一致4800【代码设置的是4800】,切记一定要点HEX发送,不然不会出现屏幕显示和发送内容一致。(原因如下)
常见的转换的函数用 itoa strtoul strtol atoi atof。多个字节转化要使用移位,取反等操作。还搞不清这个概念也真是丢脸。
首先,底层的数据传输都是字节流,所以不管选择什么方式,都会被分解为一个一个的字节。
1、选择Hex发送就代表你要发送的内容是纯数字,由程序完成String到Int再到Byte的转化。所以你应该保证每个你要发送的数都是两位的,如果是7就应该写07,因为程序会每两位每两位地读。如果你选择了Hex发送,而输入的又是字符,比如你写了ab,那么就会被程序读为16进制的AB。这就是不同的概念了,无论你选择什么方式显示都不能得到原来的ab了。
2、选择ASCII发送就代表你要发送的是字符串,这时候程序就会一位一位地读,比如你写了1234,在字节流中传递的就是123对应的ASCII码,31,32,33,34(十六进制的)。比较而言,在Hex发送模式下,写了1234,会被发送的就是12,34,如果是01020304那就是01,02,03,04。这个时候,你写ab就会发送相应的ASCII码61,62,其他字符同理。
到这里,数据已经发送出去了,接下来就是显示的问题。是显示模式,不是解析,不存在解析。
3、选择Hex显示就是把字节转化为16进制整型,你收到的是12,34,就显示为12,34,你收到31,32,33,34,也显示为31,32,33,34,如果收到AB呢,那也是AB。
4、选择ASCII显示呢,就会把你接收到的十六进制转化为对应的字符,比如你收到了31,就会显示为1。这种模式下可能会出现乱码,原因就是ASCII码只从0-7f。如果你在十六进制发送模式下发送了字符,比如发送了ab,那你就会收到AB,这个并没有ASCII码对应的字符。
所以在Hex模式下如果输入字符,是无论如何接收不到正确的数据的,其他方式那就随意了。重要的是,方式的选择改变的不是数据本身,而是数据的表现形式。
当我们以F103为发送端时候,USB转485的连接PC【使用USB串口助手为接收端】,
实现功能:F103代码写入一个数据数组,并且在LCD屏幕显示,当烧入代码后,打开串口调试助手,观察USB-485的串口接收数据是否和发送端一致。
基本到这所有的数据收发已经完成,有需要帮助调试源码的小伙伴留下联系方式,可帮助进行调试。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。