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
- stm32之RS485
- stm32---RS485初始化
- STM32 RS485通信
- stm32 RS485 SP3485
- STM32 RS485通信应用
- STM32的RS485调试过程记录
- RS485
- RS485
- RS485
- STM32菜鸟成长记录---RS485通讯协议的应用
- 转载:STM32菜鸟成长记录---RS485通讯协议的应用
- STM32再学习——实现完美的RS485
- STM32再学习——实现完美的RS485
- STM32菜鸟成长记录---RS485通讯协议的应用
- 关于STM32串口调试RS485时自动进入接收中断
- STM32 基于串口RS485双机通信原理浅析
- STM32 用RS485进行半双工通信出现的问题
- STM32菜鸟成长记录---RS485通讯协议的应用
- Servlet 的作用域(scope)
- MySQL的C++封装
- Android开发环境配置
- 深入理解Java Class文件格式(六)
- Java并发编程之线程管理(基本线程同步6)
- stm32之RS485
- 线段树扫描线面积并hdu1542
- <<The C Programming Language>>学习之路-练习题参考答案 1-4
- The database returned no natively generated identity value
- 【机器学习系列】scikit-learn中的Linear Regression Example
- 10天学会英语常见词根后缀
- Android开发出现错误:Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
- hdu 1754 I Hate It
- ORA-28002 密码过期警告