STM32学习笔记 IO口模拟串口 (接收采用定时器方式)

这篇具有很好参考价值的文章主要介绍了STM32学习笔记 IO口模拟串口 (接收采用定时器方式)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

        硬件:基于STM32F407VET6编写

        软件:使用两个GPIO口,一个用作串口发送TX,一个用作串口接收RX,采用的是定时器模拟                     时序。

二、串口简介

        要模拟串口,首先肯定是需要了解串口的协议,根据协议来编写程序。

        stm32 gpio模拟串口,stm32,单片机,嵌入式硬件

        UART的通信方式是由1个起始位,8个数据位,包含一个奇偶校验位,和结束位构成 。在本次的设计中默认为波特率为9600,停止位为1位,8位数据位,无奇偶校验位。

        先介绍起始位,从高电平跳变为低电平,表示通信开始。再来简单介绍下波特率,单位时间内传送码元符号的个数,波特率9600,也就是1s内传送9600个bit,一个bit所需要的时间为 1000000us / 9600 = 104.166 us,也就是104us。

三、程序实现

3.1 头文件参数定义

#ifndef _S_UART_H_
#define _S_UART_H_

#include "sys.h"
#include "delay.h"


//定义通信波特率
#define BaudRate_9600	104		//1000000us/9600=104.1666	发送1个位所需要的时间


//GPIO定义
#define S_Uart_Tx PCout(3)    //模拟串口TX端
#define S_Uart_Rx PCin(4)     //模拟串口RX端


typedef enum{
	State_State = 0,        //起始状态
	State_transfer,         //传输状态
	State_Stop,	            //停止状态
}UartState;

#define SUartLength		200            //模拟串口缓冲区长度
extern u8 SUartCnt;                    //模拟串口缓冲区位置
extern u8 SUartBuff[SUartLength];      //模拟串口缓冲区


void S_Uart_GPIO_Init(void);
void S_Uart_Send_Buff(u8 *buff,u8 length);
u8 S_Uart_Rx_Handler(u8 *buf,u8 *length);

#endif

3.2 GPIO的初始化        

//模拟串口GPIO初始化
void S_Uart_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	EXTI_InitTypeDef EXTI_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	//开时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);		
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);

	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;				//TX	GPIOC3
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;		//推挽输出
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;		
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;			//上拉
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
	S_Uart_Tx = 1;

	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;				//RX	GPIOC4
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;			//上拉输入
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOC,&GPIO_InitStruct);	
}

3.3 模拟串口发送        

//模拟串口发送一个字节
void S_Uart_One_Tx(u8 Data)
{
	u8 i;

	S_Uart_Tx=0;		//起始位
	delay_us(BaudRate_9600);

	for(i=0; i<8; i++)
	{
		if(Data & 0x01)			//串口协议 先发LSB
			S_Uart_Tx = 1;
		else 
			S_Uart_Tx = 0;

		delay_us(BaudRate_9600);
		Data >>= 1;
	}
	
	S_Uart_Tx = 1;
	delay_us(BaudRate_9600);
}

//模拟串口发送数据
void S_Uart_Send_Buff(u8 *buff,u8 length)
{
	for(u8 i=0; i<length; i++)
	{
		S_Uart_One_Tx(buff[i]);	
	}
}

  3.4 模拟串口接收

        需要开启一个定时器中断,对模拟串口的电平进行监视,废话不多说,直接上代码。

void Time4_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef Tim4_TimeBaseStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);

	Tim4_TimeBaseStruct.TIM_Period = arr;			//重载值
	Tim4_TimeBaseStruct.TIM_Prescaler = psc;		//预分频值
	Tim4_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
	Tim4_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInit(TIM4,&Tim4_TimeBaseStruct);
	
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
	TIM_Cmd(TIM4,ENABLE);
	
	NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;	
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStruct);
}

void TIM4_IRQHandler(void)
{		
	static u8 value=0;
	static UartState M_State = State_State;
	static u8 bit_cnt;
	
	if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM4,TIM_FLAG_Update);		
		
		if(S_Uart_Rx==0 && M_State == State_State)			//起始位 下降沿
		{
			M_State = State_transfer;			//接收到起始位,状态为传输中
			bit_cnt=0;
		}
		else if(M_State == State_transfer)
		{
			bit_cnt++;						
			if(S_Uart_Rx)
			{
				value |= (1<<(bit_cnt-1));
			}
			else 
			{
				value &= ~(1<<(bit_cnt-1));
			}
			if(bit_cnt >= 8)
				M_State = State_Stop;
		}
		else if(S_Uart_Rx && M_State==State_Stop)
		{
			bit_cnt=0;
			if(SUartCnt < SUartLength)
				SUartBuff[SUartCnt++] = value;			//存入缓冲区
			else 
				SUartCnt = 0;
			M_State = State_State;                      //状态回到起始状态,坐等下一帧数据
		}		
	}
}

//接收串口数据处理
u8 S_Uart_Rx_Handler(u8 *buf,u8 *length)
{
	*length = 0;
	if(SUartCnt > 0)			//模拟串口缓冲区不为空
	{
		*length = SUartCnt;			
		memcpy(buf,SUartBuff,*length);		//
		
		SUartCnt = 0;
	}	
	return *length;
}

3.5 主函数调用

int main(void)
{  
	u16 i;
	u8 len;
	//u8 buff[5]={0,1,2,3,4};
	u8 buff[200];
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);		//延时初始化 
	LED_Init();		  		//初始化与LED连接的硬件接口  

	S_Uart_GPIO_Init();	//模拟串口
	Time4_Init(BaudRate_9600,84-1);			//104us	
	
	while(1)
	{		
		
		if(S_Uart_Rx_Handler(buff,&len))			
		{
			S_Uart_Send_Buff(buff,len);					//将接收到的数据发送出去
		}
		
		
		if(++i %100 == 0)
		{
			i=0;
			LED0 = !LED0;
			//S_Uart_Send_Buff(buff,5);
		}
		delay_ms(10);
	}
}

四、程序执行效果

stm32 gpio模拟串口,stm32,单片机,嵌入式硬件

单片机将模拟串口接收到的数据用模拟串口发送出去。 

 好了,内容到此结束了,制作不易,如果对大家有帮助麻烦点个赞,谢谢!文章来源地址https://www.toymoban.com/news/detail-791478.html

到了这里,关于STM32学习笔记 IO口模拟串口 (接收采用定时器方式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32入门笔记10_USART串口通信+案例:上位机控制LED亮灭(USART串口通信、TIM定时器、EXTI综合案例)

    通信的目的: 将一个设备的数据传送到另一个设备, 扩展硬件系统 通信协议: 制定通信的规则, 通信双方按照协议规则进行数据收发 名称 引脚 双工 时钟 电平 设备 USART TX、RX 全双工 异步 单端 点对点 I2C SCL、SDA 半双工 同步 单端 多设备 SPI SCLK、MOSI、MISO、CS 全双工 同步 单端

    2024年02月09日
    浏览(41)
  • 【STM32】STM32学习笔记-定时器定时中断 定时器外部时钟(14)

    1.1 TIM_InternalClockConfig 1.2 TIM_TimeBaseInit 1.3 TIM_TimeBaseInitTypeDef 1.4 TIM_ClearFlag 1.5 TIM_ITConfig 1.6 TIM_Cmd 1.7 中断服务函数 参考程序 1.8 TIM_ETRClockMode2Config timer.h timer.c main.c timer.h timer.c main.c 09-定时器定时中断.rar 10-定时器外部时钟.rar 参考: 【STM32】江科大STM32学习笔记汇总

    2024年02月03日
    浏览(56)
  • 【STM32】学习笔记(TIM定时器)

    定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发

    2024年02月09日
    浏览(43)
  • stm32——hal库学习笔记(定时器)

    使用纯软件(CPU死等)的方式实现定时(延时)功能 使用精准的时基,通过硬件的方式,实现定时功能 递增计数模式实例说明 中心对齐模式实例说明 TIM6 和TIM7 控制寄存器 1(TIMx_CR1) TIM6 和TIM7 DMA/中断使能寄存器(TIMx_DIER) TIM6 和TIM7 状态寄存器(TIMx_SR) TIM6 和TIM7 计数器(TIMx_CNT)

    2024年02月21日
    浏览(56)
  • stm32学习笔记-6TIM定时器

    注:笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注:工程及代码文件放在了本人的Github仓库。 定时器是STM32中功能最强大、结构最复杂的一个外设。定时器将包括四部分8小节: 第一部分主要讲定时器基本定时的功能,也就是指定一个时间,让

    2024年02月15日
    浏览(57)
  • 基于STM32CubeMX和keil采用STM32F407的基本定时器中断实现LED闪烁

    定时器有三种,基本定时器,通用定时器,以及高级定时器。 这篇博客以最简单的基本定时器为例,实现LED的闪烁。 后面两种定时器的用法后面再写。 实现功能: TIM6控制LED每隔0.5s变一次状态。 TIM7控制LED1常量2s后熄灭。 因为都是用到LED,所以和上一篇基于STM32CubeMX与keil采

    2024年02月04日
    浏览(64)
  • 正点原子--STM32基本定时器学习笔记(1)

    目录 1. 定时器概述 1.1 软件定时原理 1.2 定时器定时原理 1.3 定时器分类 1.4 定时器特性表 1.5 基本、通用、高级定时器的功能整体区别 2. 基本定时器简介 3. 基本定时器框图 时钟树分析 这部分是笔者对基本定时器的理论知识进行学习与总结!主要记录学习过程中遇到的重难点

    2024年02月19日
    浏览(58)
  • 【STM32】学习笔记(TIM定时器)-江科大

    定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发

    2024年02月10日
    浏览(53)
  • STM32定时器实现红外接收与解码

             红外遥控是一种比较常用的通讯方式,目前红外遥控的编码方式中,应用比较广泛的是NEC协议。NEC协议的特点如下: 载波频率为 38KHz 8 位地址和 8位指令长度 地址和命令2次传输(确保可靠性) PWM 脉冲位置调制,以发射红外载波的占空比代表“0”和“1”    

    2024年02月03日
    浏览(35)
  • 【个人笔记】51单片机串口通信的字符串接收和发送,串口通信调节数码管显示时钟(串口通信,定时器,数码管)

           目的:利用PROTUES仿真软件、串口调试助手、虚拟串口,搭建单片机与PC通信仿真平台,熟悉单片机串口的配置及与PC机的通信方法;尝试制定通信协议,单片机根据通信协议解析接收到的内容,并根据接收的指令执行相应的操作。 基本功能: 1.时分秒的动态显示。

    2024年02月11日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包