用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

代码分享    -  云代码空间

——

STM32F103VB 的485多机通信

2020-10-05|26阅||

摘要:#include "sys.h"            #include "rs485.h"   #include "delay.h" #include"KEY.h" #ifdef EN_USART1_RX     //如果使能了bai接收       //接收缓存区     

#include "sys.h"           
#include "rs485.h"  
#include "delay.h"
#include"KEY.h"
#ifdef EN_USART1_RX     //如果使能了bai接收      
//接收缓存区   
 
u8 RS485_RX_BUF[96];     //接收缓冲du,最大64个字节zhi.
//接收到的数据长度
u8 RS485_RX_CNT=0;   
void USART1_IRQHandler(void)
{
    u8 res;        
    if(USART1->SR&(1<<5))//接收到数dao据  
    /*也就是RXNE置位 相当于if(USART_GetITStatus(USART1, USART_IT_RXNE))     */
    {    
        res=USART1->DR;//读取接收到的值,相当于res=USART_ReceiveData(USART1)            
        if(RS485_RX_CNT<96)
        {
            RS485_RX_BUF[RS485_RX_CNT]=res;     //记录接收到的值
            RS485_RX_CNT++;                     //接收数据增加1 
        } 
    }                                              

#endif                                       
//初始化IO 串口2
//pclk1CLK1时钟频率(Mhz)
//bound:波特率   
void RS485_Init(u32 bound)
{      
    /*float temp;
    u16 mantissa;
    u16 fraction;*/
    /*关于波特率的计算
    */     
/*  temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV
    mantissa=temp;               //得到整数部分
    fraction=(temp-mantissa)*16; //得到小数部分   
    mantissa<<=4;
    mantissa+=fraction; 
    RCC->APB2ENR|=1<<8;     //使能PORTG口时钟  
   GPIOG->CRH&=0XFFFFFF0F;  //IO状态设置
    GPIOG->CRH|=0X00000030;  //IO状态设置      
  
    RCC->APB2ENR|=1<<2;     //使能PORTA口时钟  
    GPIOA->CRL&=0XFFFF00FF;  //IO状态设置
    GPIOA->CRL|=0X00008B00;  //IO状态设置      
 
    RCC->APB1ENR|=1<<17;     //使能串口时钟 
           
    RCC->APB1RSTR|=1<<17;   //复位串口2
    RCC->APB1RSTR&=~(1<<17);//停止复位         
    //波特率设置
   USART2->BRR=mantissa;   // 波特率设置    
    USART2->CR1|=0X200C;   //1位停止,无校验位.
#ifdef EN_USART2_RX              //如果使能了接收
    //使能接收中断
    USART2->CR1|=1<<8;     //PE中断使能
    USART2->CR1|=1<<5;     //接收缓冲区非空中断使能          
 
    MY_NVIC_Init(3,3,USART2_IRQChannel,2);//组2,最低优先级 
#endif
    RS485_TX_EN=0;          //默认为接收模式
    */ 
 
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
    RCC_APB2Periph_USART1, ENABLE);//使能 GPIOA,USART1 时钟
    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能串口 2 时钟
 
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;          //PA 端口配置  控制接收模式
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  //PA2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA3
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
 
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1,ENABLE);//复位串口 2
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1,DISABLE);//停止复位
 
    #ifdef EN_USART1_RX        //如果使能了接收
    USART_InitStructure.USART_BaudRate = bound;//一般设置为 9600;
    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); ; //初始化串口
 
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口 2 中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级 2 级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级 2 级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化 NVIC 寄存器
 
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
    USART_Cmd(USART1, ENABLE);                     //使能串口
    #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((USART1->SR&0X40)==0);//等待发送结束 判断TC位的值 1 发送完成  
        //TXE 的值1  发送数据寄存器为空,它为1  TC为1  才是发送结束         
        USART1->DR=buf[t];   //向数据缓冲器写入下一个要发送的数据
    }    
    while((USART2->SR&0X40)==0);//等待发送结束 发送完前TC一直为0 ,进入死循环。
    //发送结束TC为1  结束死循环。
    RS485_RX_CNT=0;   
    RS485_TX_EN=0;              //设置为接收模式
    */
    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;  
 
            LED_Show(i,buf) ;
        }      
 
        *len=RS485_RX_CNT;  //记录本次数据长度
        RS485_RX_CNT=0;     //清零
    }*/
    if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了
    {
        for(i=0;i<rxlen;i++)
        {
            buf=RS485_RX_BUF;
            LED_Show(i,buf) ;
        }
        *len=RS485_RX_CNT;  //记录本次数据长度
        RS485_RX_CNT=0;    //清零
    }
}
顶 1踩 0收藏
分享到:
更多
文章评论
    发表评论

    个人资料

    • 昵称: 代码分享
    • 等级: 中级程序员
    • 积分: 166
    • 代码: 0 个
    • 文章: 2 篇
    • 随想: 0 条
    • 访问: 1 次
    • 关注

    人气代码

      标签

      最新提问

        站长推荐