OpenEdv-开源电子网

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

请教大神关于485的

[复制链接]

8

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2016-8-16
在线时间
19 小时
发表于 2016-9-5 13:55:14 | 显示全部楼层 |阅读模式
5金钱
开机后自动每隔1s就通过485发送一次数据,不发送的时候就置0,请问该怎么写呢?或者说我可以参考哪个章节,新人还没看完所有的资料。

最佳答案

查看完整内容[请看2#楼]

不懂你这置0是啥意思,送你比较通用的串口程序,支持普通的串口收发、支持485、支持库版本和寄存器版本的选择性编译, usart1.c文件如下 [mw_shl_code=c,true]#include #include "usart1.h" #include "delay.h" /* 最大缓存 */ #define MAXRECV USART1_BUFF static u8 RX_BUFF[MAXRECV]={0}; //接收缓冲 static u32 RX_SIZ=0; //接收到的数据长度 #if (USART1_485_EN == 1) #define RS485_TX_EN ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

219

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2014-4-14
在线时间
76 小时
发表于 2016-9-5 13:55:15 | 显示全部楼层
本帖最后由 GS1101923161 于 2016-9-5 16:31 编辑

不懂你这置0是啥意思,送你比较通用的串口程序,支持普通的串口收发、支持485、支持库版本和寄存器版本的选择性编译,
usart1.c文件如下
[mw_shl_code=c,true]#include <string.h>
#include "usart1.h"
#include "delay.h"

/* 最大缓存 */
#define MAXRECV USART1_BUFF
static u8 RX_BUFF[MAXRECV]={0};  //接收缓冲
static u32 RX_SIZ=0;               //接收到的数据长度  

#if (USART1_485_EN == 1)
#define RS485_TX_EN        PAout(8)        //485模式控制.0,接收;1,发送.
#endif

/*********************************************************
  * @function  usart1_Configuration
  * @role      USART1串口初始化
  * @input     bound:波特率
  * @output    None
  * @return    None
  ********************************************************/
#if USART1_SYS
void usart1_Configuration(u32 bound)
{           
        float temp;
        u16 mantissa;
        u16 fraction;           
        temp=(float)(72*1000000)/(bound*16);//得到USARTDIV
        mantissa=temp;                                 //得到整数部分
        fraction=(temp-mantissa)*16; //得到小数部分         
    mantissa<<=4;
        mantissa+=fraction;
        
#if (USART1_MAP_EN == 0)
        RCC->APB2ENR|=1<<2;   //使能PORTA口时钟  
        RCC->APB2ENR|=1<<14;  //使能串口时钟
        GPIOA->CRH&=0XFFFFF00F;//IO状态设置
        GPIOA->CRH|=0X000008B0;//IO状态设置
#else
        RCC->APB2ENR|=((1<<0)|(1<<3));   //使能PORTB\AFIO口时钟
        RCC->APB2ENR|=1<<14;             //使能串口时钟
        AFIO->MAPR|=1<<2;                                 //使能端口重映射
        GPIOB->CRL&=0X00FFFFFF;//IO状态设置
        GPIOB->CRL|=0X8B000000;//IO状态设置
#endif
        
#if USART1_485_EN
        /* 485的RE脚设置,根据实际情况在这里添加寄存器模式下的初始化代码*/        
#endif

        RCC->APB2RSTR|=1<<14;   //复位串口1
        RCC->APB2RSTR&=~(1<<14);//停止复位                     
        //波特率设置
         USART1->BRR=mantissa; // 波特率设置         
        USART1->CR1|=0X200C;  //1位停止,无校验位.
          //如果使能了接收
        //使能接收中断
        USART1->CR1|=1<<8;    //PE中断使能
        USART1->CR1|=1<<5;    //接收缓冲区非空中断使能                    
        MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
}

#else
void usart1_Configuration(u32 bound)
{        
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

#if (USART1_MAP_EN == 0)
        /* config USART1 clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        //PA9 TX
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);   
        
        //PA10 RX
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
#else
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);//开启端口B和复用功能时钟
        GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);//使能端口重映射
        //uart 的GPIO重映射管脚初始化
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//悬空输入
        GPIO_Init(GPIOB,&GPIO_InitStructure);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
#endif
        
#if (USART1_485_EN == 1)
        //RE PA.8
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                 //输入输出控制IO               
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(GPIOA, &GPIO_InitStructure);        
#endif

        /* USART1 mode config */
        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; //使能串口1中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级3级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
        NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
   
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
    USART_Cmd(USART1, ENABLE);                    //使能串口
        USART_ClearFlag(USART1, USART_FLAG_TC);       // 清标志
        RX_SIZ = 0;

#if (USART1_485_EN == 1)
        RS485_TX_EN=0;                        //默认为接收模式
#endif
}
#endif

/*********************************************************
  * @function  USART1_IRQHandler
  * @role      串口接收中断
  * @input     None
  * @output    None
  * @return    None
  ********************************************************/
void USART1_IRQHandler(void)
{
        u8 buff = 0;
#if USART1_SYS
        if(USART1->SR&(1<<5))//接收到数据
        {         
                if(RX_SIZ < MAXRECV){
                        buff = USART1->DR;//记录接收到的值
                        if(buff || RX_SIZ){
                                RX_BUFF[RX_SIZ++]  = buff;
                        }
                }                                                                                             
        }
#else
         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收到数据
        {                  
                if(RX_SIZ < MAXRECV){
                        buff = USART_ReceiveData(USART1);//记录接收到的值
                        if(buff || RX_SIZ){
                                RX_BUFF[RX_SIZ++]  = buff;
                        }
                }
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);    //清除中断标志.
        }

        if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)//溢出?
        {
                USART_ClearFlag(USART1,USART_FLAG_ORE);//读SR
                USART_ReceiveData(USART1);//读DR?
        }        
#endif
}

/*********************************************************
  * @function  usart1_Send
  * @role      发送len个字节.
  * @input     要发送的数据与长度,
               (为了和本代码的接收匹配,这里建议不要超过 MAXRECV 个字节)
  * @output    None
  * @return    None
  ********************************************************/
void usart1_Send(u8 *buf,u32 len)
{
        u32 t;
#if (USART1_485_EN == 1)
        RS485_TX_EN=1;
#endif
        
#if USART1_SYS
        for(t=0;t<len;t++)
        {
                while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
                USART1->DR = (u8) buf[t];         
        }
        while((USART1->SR&0X40)==0);//等待发送结束
#else        
          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);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET){//发送一个字符完成产生中断
                USART_ClearITPendingBit(USART1 ,USART_IT_TXE);//清发送中断
        }        
#endif
        
#if (USART1_485_EN == 1)
        RS485_TX_EN=0;
#endif
}

/*********************************************************
  * @function  usart1_Receive
  * @role      RS232查询接收到的数据
  * @input     buf:接收缓存首地址,与缓存长度
  * @output    None
  * @return    接收的数据长度
  ********************************************************/
u32 usart1_Receive(u8 *buf, u32 buflen)
{
        u32 rxlen=RX_SIZ;
        u32 i=0;
        u32 ret = 0;        //默认为0               
        delay_ms(10);                //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
        if(rxlen==RX_SIZ && rxlen)//接收到了数据,且接收完成了
        {
                for(i=0;(i < rxlen) && (i < (buflen - 1));i++)
                {
                        buf=RX_BUFF;
                        RX_BUFF = 0;                        
                }               
                buf='\0';
                ret=i;        //记录本次数据长度
                RX_SIZ=0;                //清零
        }
        return ret;
}

/*********************************************************
  * @function  usart1_FreeBuff
  * @role      清空缓存中的数据
  * @input     None
  * @output    None
  * @return    None
  ********************************************************/
void usart1_FreeBuff(void)
{
        int rxlen=RX_SIZ;
        int i=0;
        delay_ms(10);                //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
        while(rxlen)
        {
                if(rxlen==RX_SIZ && rxlen)//接收到了数据,且接收完成了
                {
                        for(i=0;(i<rxlen) && (i < (MAXRECV-1)) ;i++){
                                RX_BUFF = 0;
                        }        
                        RX_SIZ=0;                //清零
                }
                delay_ms(10);                //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
                rxlen=RX_SIZ;
        }
}

[/mw_shl_code]

usaert1.h文件如下
[mw_shl_code=c,true]
#ifndef __USART1_H_
#define __USART1_H_
#include "sys.h"

#define USART1_SYS      1    //设置编译版本,0是库版本,1是寄存器版本
#define USART1_BUFF     200  //接收数据缓存
#define USART1_485_EN   0    //1 开启485功能,0 关闭485功能
#define USART1_MAP_EN   0    //1 开启重定向功能,0关闭重定向功能

void usart1_Configuration(u32 bound);
void usart1_Send(u8 *buf,u32 len);
u32  usart1_Receive(u8 *buf, u32 buflen);
void usart1_FreeBuff(void);

#endif
[/mw_shl_code]
其他的几个串口都可以参考这个模式写。


回复

使用道具 举报

70

主题

6761

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13104
金钱
13104
注册时间
2012-11-26
在线时间
3811 小时
发表于 2016-9-5 14:56:34 | 显示全部楼层
不懂你的需求  什么叫不发送就置0
回复

使用道具 举报

80

主题

268

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2014-8-11
在线时间
84 小时
发表于 2016-9-5 15:28:00 | 显示全部楼层
不懂你说的置零干嘛用   失能485发送数据?还是你发送完数据是要等待响应所以让485处于接收状态     
我是一只菜鸟,但我会大鹏展翅
回复

使用道具 举报

8

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2016-8-16
在线时间
19 小时
 楼主| 发表于 2016-9-5 16:31:03 | 显示全部楼层
战舰水手 发表于 2016-9-5 15:28
不懂你说的置零干嘛用   失能485发送数据?还是你发送完数据是要等待响应所以让485处于接收状态

就是通过485发送一次后,等待1s之后再发一次,这1s里处于接收状态
回复

使用道具 举报

8

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2016-8-16
在线时间
19 小时
 楼主| 发表于 2016-9-5 16:32:40 | 显示全部楼层
GS1101923161 发表于 2016-9-5 16:29
不懂你这置0是啥意思,送你比较通用的串口程序,支持普通的串口收发、支持485、支持库版本和寄存器版本的选 ...

这么好的玩意哪儿找的?
回复

使用道具 举报

14

主题

219

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2014-4-14
在线时间
76 小时
发表于 2016-9-5 16:43:31 | 显示全部楼层
看到我发的代码了么?利用我的那个代码,你可以这么做,在usart1.h文件中设置模式为485模式,根据板子,在usaer1.c文件中修改RE脚,然后代码如下
[mw_shl_code=c,true]
int main()
{
        int i = 0;
        char buff[200]="";//数据接收缓存
        int len = 0; //数据接收长度
        int tim = 0; //声明个计时用的变量
        delay_init();//初始化延时函数
        usart1_Configuration(115200);//初始化485的引脚,及波特率等

        while(1)
        {
                if(tim++ >= 1000)
                {
                        tim = 0; //1秒时间到了
                        usart1_Send("test data",strlen("test data"));
                }
                len = usart1_Receive(buff, sizeof(buff));
                if(len)
                {
                        //接收到数据,长度为len
                        for(i = 0;i<len;i++)
                        {
                                printf("0x%02X ", buff);
                        }
                        printf("\n");
                }
                delay_ms(1);
        }
}[/mw_shl_code]







回复

使用道具 举报

14

主题

219

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2014-4-14
在线时间
76 小时
发表于 2016-9-5 16:46:39 | 显示全部楼层
HOTWAR 发表于 2016-9-5 16:32
这么好的玩意哪儿找的?

我自己写的,我只有103和407的,103的5个串口都这么整理好了,407的除了没有寄存器设置,其他都有,哈哈哈~~
回复

使用道具 举报

8

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2016-8-16
在线时间
19 小时
 楼主| 发表于 2016-9-5 16:48:28 | 显示全部楼层
GS1101923161 发表于 2016-9-5 16:46
我自己写的,我只有103和407的,103的5个串口都这么整理好了,407的除了没有寄存器设置,其他都有,哈哈 ...

厉害厉害
回复

使用道具 举报

14

主题

219

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2014-4-14
在线时间
76 小时
发表于 2016-9-5 16:49:34 | 显示全部楼层

哥的心血,别糟蹋了,哈哈~~整理这个特累
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-26 04:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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