一、串口协议和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博客

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐