【stm32】——使用标准库点亮led及UART串口通信程序开发
目录
一、串口协议和RS-232标准,以及RS232电平与TTL电平的区别
三、STM32系统给上位机(win10)连续发送“hello word”
四、STM32以查询方式接收上位机(win10)串口发来的数据
一、串口协议和RS-232标准,以及RS232电平与TTL电平的区别
(1)串口通信协议
- 是一种数据传输协议,常用于计算机和其他设备之间的通信。
- 它定义了数据传输的规则,如数据格式、传输速率等。
(2)RS-232标准
- 是一种标准的串口通信协议。
- 定义了数据传输的电压范围、信号线功能、连接方式和传输速率等
RS-232 标准主要规定了信号的用途,通讯接口以及信号的电平标准。
由于RS-232电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL校准”的电平信号,才能实现通讯。
(3)RS232电平与TTL电平的区别
根据通讯使用的电平标准不同,串口通讯可分为 TTL标准和 RS-232标准

从表中可以看出,逻辑电压不同,在电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,它使用-15V表示逻辑 1,+15V 表示逻辑 0。
(4)USB/TTL转232“模块(CH340芯片为例)
USB主机检测到USB转串口设备插入后,首先会对设备复位,然后开始USB枚举过程。USB枚举时过程会获取设备描述符、配置描述符、接口描述符等。描述符中会包含USB设备的厂商ID,设备ID和Class类别等信息。操作系统会根据该信息为设备匹配相应的USB设备驱动。
USB虚拟串口的实现在系统上依赖于USB转串口驱动,一般由厂家直接提供,也可以使用操作系统自带的CDC类串口驱动等。驱动主要分为2个功能,其一注册USB设备驱动,完成对USB设备的控制与数据通讯,其二注册串口驱动,为串口应用层提供相应的实现方法。
二、使用标准库点亮led灯
(1)操作stm32GPIO口的操作:
1.使用RCC开启GPIO时钟
2.使用GPIO_Init函数初始化GPIO口
3.使用输入输出的函数控制GPIO口
给指定端口给定想要的高低电平,本文采用高电平熄灭、低电平点亮的模式。
(2)相关函数
1)开启APB2 时钟
语法如下:
RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
第一个参数是选择输出端口,通常为GPIOA、GPIOB等,第二个参数是选择状态,使能(ENABLE)和失能(DISABLE)二选一
具体代码如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PC端口时钟
2)GPIO_Init函数
结构体的类型为:GPIO_InitTypeDef
该结构体的成员有三个,分别为:GPIO_Pin、GPIO_Speed、GPIO_Mode。
使用该函数之前需要先定义一个结构体
代码如下:
GPIO_InitTypeDef GPIO_InitStructure;//结构体开头
//三个固定成分
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PC12端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
之后是取值引用初始化函数
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOC.12
3)GPIO输出函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//把指定端口的引脚设置为高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//把指定端口的引脚设置为低电平
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//对指定端口的引脚进行写入操作
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//对指定端口的16个引脚同时进行写入操作
(3)完整代码
#include "stm32f10x.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PC端口时钟
//总分总形式
GPIO_InitTypeDef GPIO_InitStructure;//结构体开头
//三个固定成分
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PC12端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
//结尾
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOC.12
//点亮LED
while(1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
}
}
效果图如下:

三、STM32系统给上位机(win10)连续发送“hello word”
(1)USART串口通讯
UART: 通用异步通信收发器/SCI串行通讯接口。用于异步通信,可以实现全双工收发,即通信双方同时收发;两个器件无需共享同一个时钟信号就能进行通讯,即异步通讯。数据收发单位是数据帧,工作模式为中断方式,DMA工作方式。
- UART通讯双方需要设定相同的数据格式,收的格式和发的格式完全一样,一般数据帧的格式为,格式为下图:

USART
通用同步异步收发器,USART在UART的基础上增加了同步机制,一种可被设置为同步、异步通信模式的全双工串行通讯接口。在同步模式下,发送器时钟引脚SCLK输出与SPI主模式相似的数据传输时钟,相位和极性可以通过寄存器来设置。
(2)向上位机发送“ hello word”
user.h
#include "stm32f10x.h"
void usart_init(void);
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data);
void usartSendStr(USART_TypeDef* USARTx,char *str);
user.c
#include "usart.h"
#include "stm32f10x.h"
void usart_init(void)
{
GPIO_InitTypeDef gpio_init;
USART_InitTypeDef usartStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//2.1 TX
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_init.GPIO_Pin = GPIO_Pin_9;
gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&gpio_init);
//2.2 RX
gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio_init.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&gpio_init);
usartStruct.USART_BaudRate = 115200;
usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
usartStruct.USART_Parity = USART_Parity_No;
usartStruct.USART_StopBits = USART_StopBits_1;
usartStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&usartStruct);
USART_Cmd(USART1, ENABLE );
}
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data)
{
USART_SendData(USARTx,Data);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
void usartSendStr(USART_TypeDef* USARTx,char *str)
{
uint16_t i = 0;
do{
usartSendByte(USARTx,*(str+i));
i++;
}while(*(str+i) != '\0');
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
main.c
#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"
void delay(uint16_t time)
{
uint16_t i =0;
while(time--){
i=12000;
while(i--);
}
}
int main()
{
usart_init();
GPIO_SetBits(GPIOA, GPIO_Pin_3);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
while(1)
{
// usartSendStr(USART1,"°ÂÀï¸ø\r\n");
int i = printf("Finny\r\n");
printf("%d\r\n",i);
// putchar('2');
delay(1000);
}
}
效果图如下:
四、STM32以查询方式接收上位机(win10)串口发来的数据
要求:STM32以查询方式接收上位机(win10)串口发来的数据,如果接收到“Y”则点亮链接到stm32上的一个LED灯;接收到“N”则熄灭LED灯。
led.h
#include "stm32f10x.h"
void Led_init(void);
led.c
#include "stm32f10x.h"
#include "led.h"
void Led_init(void)
{
GPIO_InitTypeDef Led_init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
Led_init.GPIO_Mode = GPIO_Mode_Out_PP;
Led_init.GPIO_Pin = GPIO_Pin_13;
Led_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &Led_init);
}
usart.h
#include "stm32f10x.h"
#include <stdio.h>
void usart_init(void);
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data);
void usartSendStr(USART_TypeDef* USARTx,char *str);
usart.c
#include "usart.h"
#include "stm32f10x.h"
void usart_init(void)
{
GPIO_InitTypeDef gpio_init;
USART_InitTypeDef usartStruct;
NVIC_InitTypeDef nvic_initStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//2.1 TX
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_init.GPIO_Pin = GPIO_Pin_9;
gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&gpio_init);
//2.2 RX
gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio_init.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&gpio_init);
usartStruct.USART_BaudRate = 115200;
usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
usartStruct.USART_Parity = USART_Parity_No;
usartStruct.USART_StopBits = USART_StopBits_1;
usartStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&usartStruct);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//ÅäÖô®¿ÚÖжÏ
USART_Cmd(USART1, ENABLE );
nvic_initStruct.NVIC_IRQChannel = USART1_IRQn;
nvic_initStruct.NVIC_IRQChannelPreemptionPriority = 1;
nvic_initStruct.NVIC_IRQChannelSubPriority = 1;
nvic_initStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_initStruct);
}
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data)
{
USART_SendData(USARTx,Data);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}
void usartSendStr(USART_TypeDef* USARTx,char *str)
{
uint16_t i = 0;
do{
usartSendByte(USARTx,*(str+i));
i++;
}while(*(str+i) != '\0');
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(uint8_t)ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return (ch);
}
int fgetc(FILE *f)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int) USART_ReceiveData(USART1);
}
实物效果如下:
LED
总结
stm32的操作使用很多封装的函数,没有寄存器操作直接,一定程度上减轻了程序员的负担,初学stm32还有很多不懂的地方需要学习。
参考链接:
串口协议和RS-232标准,RS232电平与TTL电平的区别,USB/TTL转232“模块(以CH340芯片模块为例)_232协议电平-CSDN博客STM32串口发送接收数据_stm32串口接收数据-CSDN博客
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)