• 【STM32】入门(五):串口TTL、RS232、RS485


    【STM32】STM32单片机总目录

    1、简述

    1.1 电平

    TTL :全双工 ,逻辑0对应0V,逻辑1对应3.3V或者5V,一般从单片机引脚直接引出,电平3.3或5V是与IO电平兼容;

    RS232:全双工,逻辑0对应+3V至+15V,逻辑1对应-15V至-3V ,TTL经过电平转换芯片后可以输出RS232。

    RS485:半双工,逻辑0对应-6V至-2V,逻辑1对应+2V至+6V,这里的电平指AB两线间的电压差,即差分方式传输,因此可以长距离传输

    1.2 连接方式

    除了电压不同,连接方式有所区别:

    TTL、RS232只能一对一连接;
    RS-485在总线上是允许连接多达128个收发器。
    
    • 1
    • 2

    RS232常用DB9头的定义:
    在这里插入图片描述

    1.3 传输协议

    一帧数据包由起始位、有效数据、校验位以及停止位组成。
    在这里插入图片描述
    协议参数有:波特率(9600、115200等)、有效数据长度(5~8)、校验(奇、偶、0、1、无)

    2、手册

    2.1 功能框图

    在这里插入图片描述

    2.2 中断控制

    在这里插入图片描述

    2.3 模式配置

    在这里插入图片描述

    2.4 寄存器映射

    在这里插入图片描述

    3、代码

    3.1 初始化

    • 使能GPIO时钟:RCC_AHB1PeriphClockCmd
    • 使能UART时钟:RCC_APB2PeriphClockCmd
    • GPIO引脚复用为UART:GPIO_PinAFConfig
    • GPIO配置:GPIO_InitStructure、GPIO_Init
    • UART配置:USART_InitStructure、USART_Init
    • 中断配置;NVIC_InitStructure、NVIC_Init
    void uart1_init(u32 bound)
    {   
      	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	#a)使能时钟
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); 
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); 
    	
    	#b)引脚复用映射
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
    	
    	#c)GPIO配置
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;	//GPIOA9与GPIOA10
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;      		//复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//速度50MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 			//推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;   			//上拉
    	GPIO_Init(GPIOA,&GPIO_InitStructure);         	 		//初始化PA9,PA10
       
       	#d)UART配置
    	USART_InitStructure.USART_BaudRate = bound;					//波特率设置
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//字长为8位数据格式
    	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(USART1, &USART_InitStructure); 					//初始化串口1	
      	USART_Cmd(USART1, ENABLE);  								//使能串口1 
    	USART_ClearFlag(USART1, USART_FLAG_TC);
    	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);				//开启相关中断
    	
    	#e)中断配置
      	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;      	//串口1中断通道
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;	//抢占优先级3
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		 	//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    3.2 发送

    发送一个字符:版本1

    void uart1SendChar(u8 ch)
    {      
    	while((USART1->SR&0x40)==0);  
        USART1->DR = (u8) ch;      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    发送一个字符:版本2

    void uart1SendChar(uint8_t ch)
    {
    	#a) 等待发送数据寄存器为空 
    	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	
    	
    	USART_SendData(USART1,ch)}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    发送数组

    void Usart1SendArray(uint8_t *array, uint16_t num)
    {
      	uint16_t i;
    	
    	#a)循环发送每个字符
    	for(i=0; i<num; i++)
      	{
      		uart1SendChar(array[i]);
      	}
      	
      	#b)等待发送完成
      	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    USART_FLAG_TXEUSART_FLAG_TC的详细说明

    USART_FLAG_TXE:发送缓冲区空标志,说明可以往数据寄存器写入数据了,但并不代码数据发送完成了。
    USART_FLAG_TC:发送完成标志,这个才是代表USART在缓冲区的数据发送完成了,即从机接收到了数据。
    
    • 1
    • 2

    这两个标志的区别在于,它们分别表示数据在发送过程中,在两个不同的阶段中的完成情况。

    TXE 表示数据被从发送缓冲区中取走,转移到的移位寄存器中,此时发送缓冲是空的,可以向其中补充新的数据了。
    TC  表示最后放入发送缓冲区的数据已经完成了从移位寄存器向发送信号线 Tx 上的转移。
    
    • 1
    • 2

    所以,判定数据最终发送完成的标志是 TC,而不是 TXE.

    3.3 接收

    查询中断向量表,在代码文件startup_stm32f10x_hd.s中:
    串口1USART1对应到中断函数为USART1_IRQHandler
    对应上面的中断控制配置:NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

    __Vectors       DCD     __initial_sp               ; Top of Stack
    ...
                    DCD     USART1_IRQHandler          ; USART1
    ...
    
    • 1
    • 2
    • 3
    • 4

    重载中断函数 USART1_IRQHandler,实现一个回显功能,即接收啥,发送啥

    void USART1_IRQHandler(void)  
    {
      	uint8_t ucTemp;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE)!=RESET)
    	{		
    		ucTemp = USART_ReceiveData(USART1);
        	USART_SendData(USART1, ucTemp);  
        } 
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    保腿还是保命,这是个问题
    24计算机考研调剂 | 长江大学
    LiveQing视频点播流媒体RTMP推流服务功能-如何配置资源进行轮巡播放视频轮播分屏展示
    历届蓝桥杯青少年编程比赛 计算思维题真题解析【已更新5套 持续更新中】
    更新 | 持续开源迅为RK3568驱动指南第十二篇-GPIO子系统
    独家首发“JVM超硬核笔录”,连阿里面试官都赞不绝口(超清PDF+Xmind思维导图)
    【Springboot】事件机制发布与订阅的使用实践
    【初阶数据结构题目】18.设计循环队列
    聊聊 RPA 方向的规划:简单有价值的事情长期坚持做
    c++ string用法 入门必看 超详细
  • 原文地址:https://blog.csdn.net/u010168781/article/details/126150511