完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、 串口通信协议简介
1-1 概念 1-2 常用标准 ①.RS232标准 RS232标准串口通讯结构图
RS-232 与 TTL 电平区别(232趋向高容错) ②.USB转串口(USB2TTL) USB转串口通讯结构图
原生的串口到串口结构图
2-1 引脚 TX:数据发送 RX:数据接收 SCLK :时钟,仅同步通信时使用 nRTS :请求发送(Request To Send) nCTS :允许发送(Clear To Send) 2-2 数据寄存器
1、 USART_CR1:UE、TE、RE均配置为开启 2、 以发送为例,发送过程涉及2个寄存器的值改变(发送数据寄存器----TDR) 2、 TDR发送数据后状态寄存器(USART_SR)中的TXE(empty)位置1,若TXEIE=1则产生中断,不代表数据发送成功,此时TC位置1才表示发送成功,若此时TCIE=1则产生中断(相应的读取时UE、RE使能情况下,读取数据进入接收移位寄存器后传到RDR,RXNE置1,用户可从DR寄存器中读数据,若RXNEIE=1,则产生中断)、
USART_SR:TXE,Transmit data register empty 2-3 控制器 2-4 波特率
三、 代码 3-1 固件库相关配置结构体 USART初始化结构体:USART_InitTypeDef typedef struct { uint32_t USART_BaudRate; //波特率 BRR uint16_t USART_WordLength; //字长 CR1_M uint16_t USART_StopBits; //停止位 CR2_STOP uint16_t USART_Parity; //校验控制 CR1_PCE、CR1_PS uint16_t USART_Mode; //模式选择CR1_TE、CR1_RE // 硬件流选择 CR3_CTSE、CR3_RTSE uint16_t USART_HardwareFlowControl; } USART_InitTypeDef; USART同步时钟初始化结构体:USART_ClockInitTypeDef typedef struct { uint16_t USART_Clock; // 同步时钟 CR2_CLKEN uint16_t USART_CPOL; // 极性 CR2_CPOL uint16_t USART_CPHA; // 相位 CR2_CPHA uint16_t USART_LastBit; //最后一个位的时钟脉冲 CR2_LBC } USART_ClockInitTypeDef; 3-2 固件库相关配置函数 串口初始化函数: void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) 1 中断配置函数: void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) 1 串口使能函数: void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) 1 数据发送函数: void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) 1 数据接收函数: uint16_t USART_ReceiveData(USART_TypeDef* USARTx) 1 中断状态位获取函数: ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) 1 3-3 固件库编程 编程要点 1-初始化串口需要用到的GPIO 2-初始化串口,USART_InitTypeDef 3-中断配置(接收中断,中断优先级) 4-使能串口 5-编写发送和接收函数 6-编写中断服务函数 实验1:中断接收和发送 需求:单片机给电脑发送数据,电脑上位机把数据打印出来;电脑上位机给单片机发数据,单片机接收到数据之后立马发回给电脑,并打印出来。 ‘bsp-usart.c’ #include "bsp-usart.h" static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 配置USART为中断源 */ NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; /* 抢断优先级*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 初始化配置NVIC */ NVIC_Init(&NVIC_InitStructure); } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 打开串口GPIO的时钟 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // 打开串口外设的时钟 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); // 将USART Tx的GPIO配置为推挽复用模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); // 将USART Rx的GPIO配置为浮空输入模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 配置串口的工作参数 // 配置波特率 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; // 配置 针数据字长 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 配置停止位 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(DEBUG_USARTx, &USART_InitStructure); // 串口中断优先级配置 NVIC_Configuration(); // 使能串口接收中断 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(DEBUG_USARTx, ENABLE); } /* 发送一个字节 */ void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data) { USART_SendData(pUSARTx, data); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); } /* 发送两个字节的数据 */ void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data) { uint8_t temp_h,temp_l; temp_h = (data&0xff00) >> 8 ; temp_l = data&0xff; USART_SendData(pUSARTx, temp_h); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); USART_SendData(pUSARTx, temp_l); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); } /* 发送8位数据的数组 */ void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array,uint8_t num) { uint8_t i; for( i=0; i Usart_SendByte(pUSARTx, array); } while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET ); } /* 发送字符串 */ void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str) { uint8_t i=0; do { Usart_SendByte(pUSARTx, *(str+i)); i++; }while(*(str+i) != ''); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET ); } ///重定向c库函数printf到串口,重定向后可使用printf函数 int fputc(int ch, FILE *f) { /* 发送一个字节数据到串口 */ USART_SendData(DEBUG_USARTx, (uint8_t) ch); /* 等待发送完毕 */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch); } ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 int fgetc(FILE *f) { /* 等待串口输入数据 */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(DEBUG_USARTx); } ‘bsp-usart.h’ #ifndef __BSP_USART_H #define __BSP_USART_H #include "stm32f10x.h" #include #define DEBUG_USART1 1 #define DEBUG_USART2 0 #define DEBUG_USART3 0 #define DEBUG_USART4 0 #define DEBUG_USART5 0 #if DEBUG_USART1 // 串口1-USART1 #define DEBUG_USARTx USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_IRQ USART1_IRQn #define DEBUG_USART_IRQHandler USART1_IRQHandler #elif DEBUG_USART2 //串口2-USART2 #define DEBUG_USARTx USART2 #define DEBUG_USART_CLK RCC_APB1Periph_USART2 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_2 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_3 #define DEBUG_USART_IRQ USART2_IRQn #define DEBUG_USART_IRQHandler USART2_IRQHandler #elif DEBUG_USART3 //串口3-USART3 #define DEBUG_USARTx USART3 #define DEBUG_USART_CLK RCC_APB1Periph_USART3 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOB) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOB #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_RX_GPIO_PORT GPIOB #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11 #define DEBUG_USART_IRQ USART3_IRQn #define DEBUG_USART_IRQHandler USART3_IRQHandler #elif DEBUG_USART4 //串口4-UART4 #define DEBUG_USARTx UART4 #define DEBUG_USART_CLK RCC_APB1Periph_UART4 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOC #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_RX_GPIO_PORT GPIOC #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11 #define DEBUG_USART_IRQ UART4_IRQn #define DEBUG_USART_IRQHandler UART4_IRQHandler #elif DEBUG_USART5 //串口5-UART5 #define DEBUG_USARTx UART5 #define DEBUG_USART_CLK RCC_APB1Periph_UART5 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOC #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_12 #define DEBUG_USART_RX_GPIO_PORT GPIOD #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_2 #define DEBUG_USART_IRQ UART5_IRQn #define DEBUG_USART_IRQHandler UART5_IRQHandler #endif void USART_Config(void); void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data); void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data); void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array,uint8_t num); void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str); #endif /* __BSP_USART_H */ ‘stm32f10x_it.c’ void DEBUG_USART_IRQHandler(void) { uint8_t ucTemp; if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TC) != RESET)//再次判断是否发送完毕 { ucTemp = USART_ReceiveData(DEBUG_USARTx); //接收数据 USART_SendData(DEBUG_USARTx, ucTemp); //将接收数据发送至单片机显示 } } ‘main.c’ #include "stm32f10x.h" #include "bsp-usart.h" int main(void) { USART_Config(); printf("test_printf~~n"); Usart_SendStr(DEBUG_USARTx,"test_SendStr~~n"); while(1) { // } } 串口调试助手根据‘配置串口的工作参数’选择相应参数调试
实验2:串口控制RGB灯亮灭 **需求:**电脑给单片机发命令,用于控制开发板上的RGB灯。 (与实验1相比改动部分) ‘stm32f10x_it.c’ void DEBUG_USART_IRQHandler(void) { if(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TC) != RESET) { ch = USART_ReceiveData(DEBUG_USARTx);//ch为外部引用全局变量 printf("ch = %cn", ch); } } ‘main.c’ #include "stm32f10x.h" #include "bsp-led.h" #include "bsp-usart.h" uint16_t ch = 0;//全局变量ch,用于接收串口信息 int main(void) { USART_Config(); //串口初始化 LED_GPIO_Config(); //LED初始化 while(1) { //USART判断ch的值进行RGB的状态切换 LED_USART_SWITCH(); //ch--switch函数 /***************************************/ // void LED_USART_SWITCH(void) // { // switch(ch) // { // case 0x01: LEDON_G;break; //绿灯 // case 0x02: LEDON_R;break; //红灯 // case 0x03: LEDON_B;break; //蓝灯 // default: LED_ALL(ON);break; //白灯 // } // } /***************************************/ } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
2116 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1828 浏览 1 评论
1303 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
853 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
2193 浏览 2 评论
2096浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
1002浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
386浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
717浏览 3评论
703浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-4-1 15:41 , Processed in 0.945653 second(s), Total 47, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191
|