OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3578|回复: 2

请问rs485转rs232怎么实现?

[复制链接]

0

主题

0

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2020-11-15
在线时间
4 小时
发表于 2021-1-20 12:41:41 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 支持向量鸡 于 2021-1-20 12:52 编辑

现状:
1.板子上的芯片是stm32f103zet6
2.板子上只有rs485的串口
3.但是另一个设备是rs232

已经能实现:1.板子通过rs485的串口,对rs485的设备接收、发送设计,说明设备本身硬件没问题
2.板子通过rs485的串口,对rs232的设备发送数据

未能实现:
1.板子通过rs485的串口,接收s232的设备的数据。
请问用代码怎么实现rs485转rs232呢?

目前的代码如下:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "bmp.h"
#include "rs485.h"


int main(void)
  {        
                u8 i;
                u8 t;
                u8 lenOfRs485rec;
                //最大长度为8,防止超过8字符后显示乱码
                u8 rs485rec[8];
                u8 rs485sen[9]={'a','b','c','d','e','f','g','h'};
               
                delay_init();                     //延时函数初始化         
                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
                OLED_Init();                        //初始化OLED  
                OLED_Clear()          ;
                LED_Init();
                RS485_Init(9600);        //初始化RS485
                t=0;
                OLED_Clear();
        while(1)
        {               
                RS485_Send_Data(rs485sen,8);//发送9个字节
                delay_ms(250);
                //屏幕第1行
                OLED_ShowString(1,0,"Times:",16);  
                t++;
                if(t>100)t=0;
                OLED_ShowNum(48,0,t,3,16);//显示t的值         
                //屏幕第2行
                OLED_ShowString(1,2,"send:",16);
                for(i=0;i<8;i++)OLED_ShowChar(48+i*8,2,rs485sen[0+i],16);        //显示发送的数据
                //屏幕第3行
                //通过串口1中断接收数据,储存到rs485buf,长度为lengthOfRs485rec
                OLED_ShowString(1,4,"rec:",16);
               
                RS485_Receive_Data(rs485rec,&lenOfRs485rec);
                if(lenOfRs485rec)//接收到有数据
                {
                        if(lenOfRs485rec>8)lenOfRs485rec=8;//最大是8个数据.
                         for(i=0;i<lenOfRs485rec;i++)OLED_ShowChar(40+i*8,4,rs485rec[0+i],16);        //显示接收的数据
                 }
                //屏幕第4行,暂时无内容
                delay_ms(250);
        }         
}



//==============================手动分割线,rs485.c中的代码如下========================================




//#include "oled.h"
//#include "led.h"
#include "sys.h"                    
#include "rs485.h"         
#include "delay.h"
#ifdef EN_USART1_RX           //如果使能了接收
//接收缓存区         
u8 RS485_RX_BUF[64];          //接收缓冲,最大64个字节.
//接收到的数据长度
u8 RS485_RX_CNT=0;                     
void USART1_IRQHandler(void)
{
        u8 res;            
         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //USART1接收中断,接收到数据
        {         
                //OLED_ShowString(1,6,"NVIC",16);     //用于测试是否中断,rs485成功,rs232失败?
                //LED0=0;
                res =USART_ReceiveData(USART1);         //读取接收到的数据
                if(RS485_RX_CNT<64)
                {
                        RS485_RX_BUF[RS485_RX_CNT]=res;                //记录接收到的值
                        RS485_RX_CNT++;                                                //接收数据增加1
                }
        }                                                                                          
}
#endif                                                                                 
//初始化IO 本项目使用串口1
//pclk1 : PCLK1时钟频率(Mhz)
//bound:波特率         
//RS485_TXD PA9     RS485_RXD PA10     RS485_CS PA0
void RS485_Init(u32 bound)
{  
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
         NVIC_InitTypeDef NVIC_InitStructure;

        SystemInit();     //rs232中的语句
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);        //使能USART2,PA0是USART2?
        //rs232必须有复用?
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);        
        
//RS485_CS的IO口初始化 PA0
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                                 //PA0端口配置
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(GPIOA, &GPIO_InitStructure);


//RS485_TXD的IO口初始化 PA9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;        //PA9
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽
  GPIO_Init(GPIOA, &GPIO_InitStructure);
   
//RS485_RXD的IO口初始化        PA10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
                        
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1,ENABLE);//复位串口1
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1,DISABLE);//停止复位

#ifdef EN_USART1_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(USART1, &USART_InitStructure); ; //初始化串口1
  
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口1中断
        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(USART1, USART_IT_RXNE, ENABLE);//开启接收中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1


#endif


  RS485_TX_EN=0;                        //默认为接收模式

}


//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(USART1, USART_FLAG_TC) == RESET);         
                USART_SendData(USART1,buf[t]);
        }         

        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);               
        RS485_RX_CNT=0;         
        RS485_TX_EN=0;                                //设置为接收模式        
}
//RS485查询接收到的数据
//buf:接收缓存首地址
//len:读到的数据长度
void RS485_Receive_Data(u8 *buf,u8 *len)
{
        u8 rxlen=RS485_RX_CNT;
        u8 i=0;
        *len=0;                                //默认为0
        delay_ms(10);                //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
        if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了
        {
                for(i=0;i<rxlen;i++)
                {
                        buf=RS485_RX_BUF;        
                }               
                *len=RS485_RX_CNT;        //记录本次数据长度
                RS485_RX_CNT=0;                //清零
        }
}


在中断部分有LED和OLED的两行注释,是因为我怀疑rs232的信号没能让板子进入串口中断,确实测试时OLED和LED都没有信号,所以因为rs232无法中断,结果板子收不到信号?但rs485就可以,不懂为什么?






正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2021-1-22 02:09:11 | 显示全部楼层
回复

使用道具 举报

11

主题

2149

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4915
金钱
4915
注册时间
2015-1-10
在线时间
616 小时
发表于 2021-1-22 13:46:11 | 显示全部楼层
硬件接口不一样怎么可能可以用软件实现呢,直接加个485转232模块
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-10 04:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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