stm32之RS485

来源:互联网 发布:兴安数据库工程师招聘 编辑:程序博客网 时间:2024/06/04 19:20

stm32的rs485和rs232都是用到串口通信USART,寄存器的配置几乎一样,rs485用USART2,前面博客已经讲了如何配置串口,以及rs485协议,在这里就不再多提。下面直接讲如何设置,开发板的电路如下:


本模块使用的是SP3490芯片是一种485全双工收发芯片。
下面讲一下程序设计要点:
1.配置RCC寄存器组,使用PLL输出72MHz时钟并作为主时钟源。

2.配置GPIOA端口,分别设置PA2为能推挽输出,PA3为浮空输入模式

3.配置USART设备,主要参数为:使用115200bps波特率、8位数据长度、1个停止位且无校验位、全双工模式。

下面直接上程序,分别用polling法和中断法。

polling:

#include "stm32f10x.h"#include "stdio.h"#include "stdarg.h"void RCC_Configuration(void);void GPIO_Configuration(void);void USART_Configuration(void);int fputc(int ch, FILE *f);void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...);char *itoa(int value, char *string, int radix);int main(){u16 i = 0;RCC_Configuration();GPIO_Configuration();USART_Configuration();printf("\r\nWelcome!\r\n");printf("\r\n你好,严世富\r\n");USART_OUT(USART2,"\r 好好学习,天天向上!\n");while(1){if(USART_GetFlagStatus(USART2 , USART_FLAG_RXNE) == SET)//判断接收数据寄存器非空标准位是否为1{USART_SendData(USART2,USART_ReceiveData(USART2));//向usart2发送从usart2接收的数据for(i = 0; i < 500; i++);                        //短暂延时减少出错}}}/*格式化串口输出函数*/void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...){ const char *s;    int d;    char buf[16];    va_list ap;    va_start(ap, Data);while(*Data!=0){                          //判断是否到达字符串结束符if(*Data==0x5c){  //'\'switch (*++Data){case 'r':          //回车符USART_SendData(USARTx, 0x0d);   Data++;break;case 'n':          //换行符USART_SendData(USARTx, 0x0a);Data++;break;default:Data++;    break;} }else if(*Data=='%'){  //switch (*++Data){case 's':  //字符串                s = va_arg(ap, const char *);                for ( ; *s; s++) {                    USART_SendData(USARTx,*s);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);                }Data++;                break;            case 'd':  //十进制                d = va_arg(ap, int);                itoa(d, buf, 10);                for (s = buf; *s; s++) {                    USART_SendData(USARTx,*s);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);                }Data++;                break;default:Data++;    break;} }else USART_SendData(USARTx, *Data++);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);}}/*整型数据转换为字符串函数*/char *itoa(int value, char *string, int radix){    int     i, d;    int     flag = 0;    char    *ptr = string;    /* This implementation only works for decimal numbers. */    if (radix != 10)    {        *ptr = 0;        return string;    }    if (!value)    {        *ptr++ = 0x30;        *ptr = 0;        return string;    }    /* if this is a negative value insert the minus sign. */    if (value < 0)    {        *ptr++ = '-';        /* Make the value positive. */        value *= -1;    }    for (i = 10000; i > 0; i /= 10)    {        d = value / i;        if (d || flag)        {            *ptr++ = (char)(d + 0x30);            value -= (d * i);            flag = 1;        }    }    /* Null terminate the string. */    *ptr = 0;    return string;} /* NCL_Itoa *//*时钟设置*/void RCC_Configuration(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE);  }/*GPIO口配置*/void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//USART1 TXGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//USART1 RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//复用浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;          //USART2 TXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);     //A端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;           //USART2 RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    //复用开漏输入GPIO_Init(GPIOA, &GPIO_InitStructure);}/*配置串口*/void USART_Configuration(void){USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;//波特率是115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位为8位USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位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);USART_Init(USART2, &USART_InitStructure);USART_Cmd(USART1 , ENABLE);USART_Cmd(USART2 , ENABLE); /* Enable the USARTx */}/*printf函数输出重定向 输出到USART2*/int fputc(int ch,FILE *f){USART_SendData(USART2,(u8) ch);while(USART_GetFlagStatus(USART2,USART_FLAG_TC) == RESET);return ch;}

interrupt:

main.c

#include "stm32f10x.h"#include "stdio.h"#include "stdarg.h"uint8_t TxBuffer1[] = "USART Interrupt Example: This is USART2 DEMO";  uint8_t RxBuffer1[],rec_f,tx_flag;__IO uint8_t TxCounter1 = 0x00;__IO uint8_t RxCounter1 = 0x00; void RCC_Configuration(void);void GPIO_Configuration(void);void USART_Configuration(void);void NVIC_Configuration(void);int fputc(int ch, FILE *f);void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...);char *itoa(int value, char *string, int radix);int main(){RCC_Configuration();GPIO_Configuration();USART_Configuration();NVIC_Configuration();printf("\r\nWelcome!\r\n");printf("\r\n你好,严世富\r\n");USART_OUT(USART2,"\r 好好学习,天天向上!\n");while(1){if(rec_f==1){  //判断是否收到一帧有效数据rec_f=0;USART_OUT(USART2,"\r\n您发送的信息为: \r\n");    USART_OUT(USART2,&TxBuffer1[0]);}}}/*格式化串口输出函数*/void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...){ const char *s;    int d;    char buf[16];    va_list ap;    va_start(ap, Data);while(*Data!=0){                          //判断是否到达字符串结束符if(*Data==0x5c){  //'\'switch (*++Data){case 'r':          //回车符USART_SendData(USARTx, 0x0d);   Data++;break;case 'n':          //换行符USART_SendData(USARTx, 0x0a);Data++;break;default:Data++;    break;} }else if(*Data=='%'){  //switch (*++Data){case 's':  //字符串                s = va_arg(ap, const char *);                for ( ; *s; s++) {                    USART_SendData(USARTx,*s);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);                }Data++;                break;            case 'd':  //十进制                d = va_arg(ap, int);                itoa(d, buf, 10);                for (s = buf; *s; s++) {                    USART_SendData(USARTx,*s);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);                }Data++;                break;default:Data++;    break;} }else USART_SendData(USARTx, *Data++);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);}}/*整型数据转换为字符串函数*/char *itoa(int value, char *string, int radix){    int     i, d;    int     flag = 0;    char    *ptr = string;    /* This implementation only works for decimal numbers. */    if (radix != 10)    {        *ptr = 0;        return string;    }    if (!value)    {        *ptr++ = 0x30;        *ptr = 0;        return string;    }    /* if this is a negative value insert the minus sign. */    if (value < 0)    {        *ptr++ = '-';        /* Make the value positive. */        value *= -1;    }    for (i = 10000; i > 0; i /= 10)    {        d = value / i;        if (d || flag)        {            *ptr++ = (char)(d + 0x30);            value -= (d * i);            flag = 1;        }    }    /* Null terminate the string. */    *ptr = 0;    return string;} /* NCL_Itoa *//*时钟设置*/void RCC_Configuration(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE);  }/*GPIO口配置*/void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//USART1 TXGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//USART1 RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//复用浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;          //USART2 TXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);     //A端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;           //USART2 RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    //复用开漏输入GPIO_Init(GPIOA, &GPIO_InitStructure);}/*配置串口*/void USART_Configuration(void){USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;//波特率是115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位为8位USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位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);USART_Init(USART2, &USART_InitStructure);USART_Cmd(USART1 , ENABLE);USART_Cmd(USART2 , ENABLE); /* Enable the USARTx */}/*printf函数输出重定向 输出到USART2*/int fputc(int ch,FILE *f){USART_SendData(USART2,(u8) ch);while(USART_GetFlagStatus(USART2,USART_FLAG_TC) == RESET);return ch;}/*配置中断控制器*/void NVIC_Configuration(void){  /*  结构声明*/  NVIC_InitTypeDef NVIC_InitStructure;       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);      NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;     //设置串口1中断  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     //抢占优先级 0  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级为0  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能  NVIC_Init(&NVIC_InitStructure);}

stm32fl0x_it.c

#include "stm32f10x_it.h"extern uint8_t TxBuffer1[]; extern uint8_t RxBuffer1[];extern __IO uint8_t RxCounter1; extern uint8_t rec_f,tx_flag;void USART2_IRQHandler(void)      //串口1 中断服务程序{  unsigned int i;  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)   //判断读寄存器是否非空  {        RxBuffer1[RxCounter1++] = USART_ReceiveData(USART2);   //将读寄存器的数据缓存到接收缓冲区里    if(RxBuffer1[RxCounter1-2]=='o'&&RxBuffer1[RxCounter1-1]=='k')     //判断结束标志是否是ok    {  for(i=0; i< RxCounter1-2; i++) TxBuffer1[i]= RxBuffer1[i];      //将接收缓冲器的数据转到发送缓冲区,准备转发  rec_f=1; //接收成功标志  TxBuffer1[RxCounter1-2]=0;                                     //发送缓冲区结束符      RxCounter1=0;      }  }    if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)                   //这段是为了避免STM32 USART 第一个字节发不出去的BUG   {      USART_ITConfig(USART2, USART_IT_TXE, DISABLE);     //禁止发缓冲器空中断,   }  }


0 0