stm32f407VET6 系统学习 day03 通用同步异步收发器

news2024/11/18 5:52:14

1.同步串行通信

同步通信发送端和接收端必须用 共同的时钟源 才能保持它们之间的准确同步。同步传输时,每个字
符没有起始位和停止位,它不是用起始位来标志字符的开始,而是用一串特定的二进制序列,称为
同步字符,去通知接收器串行数据的第一位何时到达。然后,串行数据信息以连续的形式发送,每
个时钟周期发送1位数据。接收器搜索到同步字符后,才开始接收数据位。因此,同步传输时数据成
批连续发送,信息字符间不留空隙,它严格按照约定的速率发送和接收。(I2C,SPi)

2.异步串行通信

异步串行通信是指串口的发送与接收设备使用 各自的时钟 控制数据的发送和接收过程,以字符为数
据传输单位,字符之间可以有间隔。需要开始位和停止位确定发送数据的开始和结束。为使双方的
收发协调,要求发送和接收设备的串口工作时钟频率要尽可能一致.

3.常见通信协议


4. 串口电路连接


5.串口通信数据帧格式

波特率 一般是115200


6.波特率


7.波特率计算


8.串口编程(初始化)


9.串口编程(收发数据)


代码:

#include "myusart.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_gpio.h"
#include "stdio.h"
u8 USART_RX_BUF[USART_REC_LEN];
u16 USART_RX_STA = 0;  //接受完成的标志

#pragma import(__use_no_semihosting)
//标准库需要的支持函数

struct __FILE
{
	int handle;
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式    

void _sys_exit(int x)
{
	x=x;
}

int fputc(int ch,FILE *f)
{
	#if 0
	while( (USART1->SR&(1<<6))==0 ); //发送未完成等待
	USART1->DR = (unsigned char)ch;  //发送完成,那么可以向DR写入下一个待发送的数据	
	return ch;
	#else
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
	USART_SendData(USART1,(unsigned char)ch);	
	return ch;
	#endif
}

int fgetc(FILE *f)
{
	#if 0
	while((USART1->SR&(1<<5)) == 0);  //数据寄存器非空(即:接收到数据),那么跳出循环,否则一直等待
	return((int)(USART1->DR&0xff));	  //接收完成,读取数据。
	#else
	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
	return((int)(USART_ReceiveData(USART1)));
	#endif
}

void myusart_init(int  usart_btl)
{
    //第一步:准备三个结构体
    USART_InitTypeDef USART_InitStruct;  // 串口通信
    NVIC_InitTypeDef NVIC_InitStruct ;   // 中断寄存器NVIC
    GPIO_InitTypeDef GPIO_InitStruct;   //GPIO设置结构体
    
    //第二步: 时钟使能
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //串口时钟使能
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //GPIO口时钟使能
    
    //第三步: 设置端口复用
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_USART1);
    //把A组中的10引脚设置成串口1模式(复用)
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_USART1);
    //
    //第四步: 设置GPIO口的模式  (PA9 --TXD   PA10 ---RXD)
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF ; //复用功能
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA ,&GPIO_InitStruct);
    GPIO_SetBits(GPIOA,GPIO_Pin_9);
    
    /*GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init( GPIOA ,&GPIO_InitStruct);*/
    
    // 第五步: 设置usart寄存器
    USART_InitStruct.USART_BaudRate = usart_btl;  // 波特率
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流
    USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;  //允许接受和发送
    USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位(无)
    USART_InitStruct.USART_StopBits = USART_StopBits_1;  //停止位 (1位)
    USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 字长 (8位)
    USART_Init(USART1,&USART_InitStruct);
     
    //第六步: 设置中断寄存器
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;   // 中断号
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;    //终端号使能
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 响应优先级
    NVIC_Init(&NVIC_InitStruct);
    
    //第七步: 设置接收中断使能   设置串口使能
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收数据中断
    USART_Cmd(USART1,ENABLE);
    
}


//发送数据 aabcdef\r\n
//串口1中断服务程序
u8 count = 0;
void USART1_IRQHandler(void)    /串口接收数据的中断            	
{

	u8 Res;
     //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d   0100 0000 0000 0000
			{
				if(Res!='\n')USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到‘\r’
			{	
				if(Res=='\r')USART_RX_STA|=0x4000;   //USART_RX_STA = 1100 0000 0000 0000
				else            //USART_RX_BUF[0] = 'd';  USART_RX_BUF[1] = 'a';..  USART_RX_BUF[4] = 'y'
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;        // danny\r\n   
					USART_RX_STA++;
                    //接收数据错误,重新开始接收	
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;  
				}		 
			}
		}   		 
  } 
} 

//进行串口通信,当用户发送01+02  串口接受到后 发送03 给到pc




/*
//main.c

SysTick_init(168);

    //中断分组
    u16 len = 0;
    int i = 0;
    SysTick_init(168);//初始化延时函数
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    myusart_init(115200);
		 
   while(1)
	{
        //数据接收完成
		if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			for(i=0;i<len;i++)
			{
				USART_SendData(USART1, USART_RX_BUF[i]);    
                //等待发送结束                
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
			}
			
			if(len == 5)
			{
					if(USART_RX_BUF[2]==43)
					{
							int a1=((int)(USART_RX_BUF[0] -48)*10 )+ (int)(USART_RX_BUF[1] -48);
							int a2=((int)(USART_RX_BUF[3] -48)*10 )+ (int)(USART_RX_BUF[4] -48);
							int a3= a1+a2; 
							if(a3<10)
							{
									printf("= 0%d \r\n",a3);
							}
							else	
							{
									printf("= %d \r\n",a3);
							}
					}
					else if(USART_RX_BUF[2]==45)
					{
							int a1=((int)(USART_RX_BUF[0] -48)*10 )+ (int)(USART_RX_BUF[1] -48);
							int a2=((int)(USART_RX_BUF[3] -48)*10 )+ (int)(USART_RX_BUF[4] -48);
							int a3= a1-a2; 
							if(a3<10)
							{
									printf("= %d \r\n",a3);
							}
							else	
							{
									printf("= %d \r\n",a3);
							}
					}
					
			}
			
			USART_RX_STA=0;
		}
	}


*/


 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/113038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[思维模式-14]:《复盘》-2- “知”篇 - 复盘之道

目录 前言&#xff1a; 一、U型学习法&#xff1a;复盘的学习机理 &#xff08;1&#xff09; 回顾、评估 &#xff08;2&#xff09;分析、反思 &#xff08;3&#xff09;萃取、提炼 &#xff08;4&#xff09;转化、应用 二、复盘与PDCA既有区别&#xff0c;也有联系…

solr 安装和使用

Solr是基于ApacheLucene构建的流行、快速、开源的企业搜索平台 Solr具有高度可靠性、可扩展性和容错性&#xff0c;提供分布式索引、复制和负载平衡查询、自动故障切换和恢复、集中配置等功能。Solr为许多世界上最大的互联网站点提供搜索和导航功能 环境准备 linux centos7 ja…

如何用iDesktop快速制作一幅研究区概况图

目录前言数据准备成果展示制作步骤前言 研究区概况图能直观展示研究区域的地理位置&#xff0c;在许多研究展示与论文撰写中必不可少。本文将以成都市为例&#xff0c;利用SuperMap桌面产品iDesktop快速制作一幅研究区概况图。 数据准备 四川省行政区划矢量数据&#xff08;…

【语音处理】LQ/QR噪声估计器研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

【Javascript】循环,函数,调用栈,闭包,递归

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录函数作用域例子调用栈可选参数闭包递归函数 形参不需要定义var&#xff0c;函数可以付给一个变量…

Android Qcom USB Driver学习(八)

该系列文章总目录链接与各部分简介&#xff1a; Android Qcom USB Driver学习(零) 因为要看usb charging的问题&#xff0c;所以需要补充一下battery的相关知识&#xff0c;算是入门吧 BAT SCH (1)VBATT_VSNS_P (2)BAT_THERM (3)I2C_SDA (4)I2C_SCL (5)VBATT_VSNS_M (1)BATT…

【问题分析】解决java中epoll依赖缺失问题

【问题分析】解决java中epoll依赖缺失问题一、前言二、问题描述三、问题分析四、解决方法五、总结一、前言 在学习使用lettuce框架实现UNIX域套接字unix domain socket连接redis时&#xff0c;遇到了一个问题&#xff0c;提示java.lang.IllegalStateException: A unix domain …

Java Stream后续来了,汇总一些项目开发中高频使用的 Stream操作

不过讲解这些操作时用的都是非常简单的例子&#xff0c;流操作的数据也都是简单类型的&#xff0c;主要的目的是让大家能更快速地理解 Stream 的各种操作应用在数据上后&#xff0c;都有什么效果。 在现实场景中实际做项目的时候&#xff0c;我们使用Stream操作的数据大多数情…

OpenCV颜色识别

颜色分辨 单个颜色识别 代码 import cv2 import numpy as npdef color(lower, upper, name):Img cv2.imread(image/origin/all.png) # 读入一幅图像kernel_3 np.ones((3, 3), np.uint8) # 3x3的卷积核if Img is not None: # 判断图片是否读入HSV cv2.cvtColor(Img, cv2…

maven中profiles使用详解,多环境开发配置文件(开发,测试,生产)+ pom中resources部分标签介绍

一.maven中profiles使用详解&#xff08;仅供参考&#xff09; 使用的场景 常常遇到一些项目中多环境切换的问题。比如在开发过程中用到开发环境&#xff0c;在测试中使用测试环境&#xff0c;在生产中用生产环境的情况。springboot中提供了 spring.profile.active的方式来实…

以mariadb为例介绍如何使用systemctl命令集设置服务开机自启动

以mariadb为例介绍如何使用systemctl命令集设置服务开机自启动一、systemd简介二、systemctl命令集常用命令三、以mariadb自启动为例四、更多说明一、systemd简介 systemd即为system daemon,是linux下的一种init软件,由Lennart Poettering带头开发,并在LGPL 2.1及其后续版本许…

[思维模式-13]:《复盘》-1- “知”篇 - 认识复盘

目录 前言 一、什么是复盘 二、复盘的三个关键词 三、复盘&#xff0c;而非总结 四、复盘的优势与局限 五、复盘与行动学习、培训、绩效改进的区别与联系 六、关于复盘的几个常见误解 误解1&#xff1a;可否对他人之事进行复盘 误解2&#xff1a;“项目后评估”是复盘吗…

细粒度图像分类模型(含实战代码)

来源&#xff1a;投稿 作者&#xff1a;lsc 编辑&#xff1a;学姐 理论部分 01细粒度图片分类问题 1.1细粒度图片分类特点 可判别区域往往只是在图像中很小的一块区域内。 1.2细粒度图像分类数据集 1.3细粒度图像分类竞赛 1.4细粒度图像分类模型分类: (1)强监督模型: 需要…

Java之AQS

AQS是什么 是用来实现锁或者其它同步器组件的公共基础部分的抽象实现&#xff0c;整体就是一个抽象的FIFO队列来完成资源获取线程的安排工作&#xff0c;并通过一个int类变量表示持有锁的状态。 使用到AQS的一些类 ReentranLock: CountDownLatch ReentrantReadWriteLock:…

Go语言开发小技巧易错点100例(四)

往期回顾&#xff1a; Go语言开发小技巧&易错点100例&#xff08;一&#xff09;Go语言开发小技巧&易错点100例&#xff08;二&#xff09;Go语言开发小技巧&易错点100例&#xff08;三&#xff09; 本期看点&#xff08;技巧类用【技】表示&#xff0c;易错点用…

_14LeetCode代码随想录算法训练营第十四天-C++二叉树

_14LeetCode代码随想录算法训练营第十四天-C二叉树 题目列表 104.二叉树的最大深度559.n叉树的最大深度111.二叉树的最小深度222.完全二叉树的节点个数 104.二叉树的最大深度 题目 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长…

RabbitMQ 第一天 基础 3 RabbitMQ 快速入门 3.1 入门程序【生产者】

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础3 RabbitMQ 快速入门3.1 入门程序3.1.1 生产者第一天 基础 3 RabbitMQ 快速入门 3.1 入门程序 3.1.1 生产者 看下文档 点进去 先就来做一个 这个简单模式 P&…

vector

目录vector的介绍和使用vector的介绍vector的使用vector 空间增长问题vector 迭代器失效问题。&#xff08;重点&#xff09;vector与erase迭代器失效的代码vector深度剖析及模拟实现vector模拟实现代码使用memcpy拷贝问题动态二维数组理解vector反向迭代器reverse_iteratorvec…

Android开发进阶——Coil对比Glide分析

Coil概述 Coil是Android上的一个全新的图片加载框架&#xff0c;它的全名叫做coroutine image loader,即协程图片加载库。 与传统的图片加载库Glide&#xff0c;Picasso或Fresco等相比。该具有轻量&#xff08;只有大约1500个方法&#xff09;、快、易于使用、更现代的API等优…

【Vue项目搭建】vue-admin-template修改(2)

接上文、、 --------------------------------------------------------- 优化登录 单独封装路由守卫 &#xff0c;设置白名单&#xff0c;permission.js&#xff0c;鉴权 跳转动画优化&#xff08;使用NProgress插件&#xff09; 显示logo svg 改填充颜色 stroke //画线颜色…