day6:STM32MP157——串口通信实验

使用的是cortex A7内核

【串口通信的工作原理】

本次实验使用的是uart4的串口,分别使用了uart4_tx和uart4_rx两个引脚。根据板子的原理图我们可以知道,他们分别对应着芯片的PG11和PB2

从引脚名字也可以知道使用了GPIO口,所以本次实验同样需要使用到GPIO模块。再加上uart模块和RCC使能模块。所以本次实验一共需要使用到三个模块。基本工作框图如下:

【RCC使能】

通过芯片手册可以知道RCC对GPIO使能使用的是AHB总线,对UART使能是通过APB1总线

再在芯片手册中直接查询这两个总线的寄存器即可知道需要对哪一位数据进行修改进行使能

具体使能操作情况如下

    //使能GPIOB,GPIOG,UART4RCC->MP_AHB4ENSETR |= (0x1 << 1);RCC->MP_AHB4ENSETR |= (0x1 << 6);RCC->MP_APB1ENSETR |= (0x1 << 16);

【GPIO功能复用】

通过查询芯片手册可知,只需要对GPIO的AFRL或者AFRH寄存器进行修改即可。

端口复用寄存器存在两个的原因:

对端口的复用需要4位,而每个寄存器只有32位,所以每个端口复用寄存器只能操作8个GPIO口。但是每个口都有16个,所以需要两个端口复用寄存器来分别控制低8位口和高8位口,AFRL就操作0-7这8个,AFRH就操作8-15这8个口

所以本次使用的两个口PB2和PG11分别要修改的寄存器为GPIOB_AFRL和AFRHG_AFRH寄存器,再根据寄存器的结构便可以知道要修改的是哪几位。

现在我们知道了需要设置哪几位,但是设置成什么数字并不知道,继续查询芯片手册,我们需要把它复用成uart4的模式。

从上面这两张表就可以知道,只需要把PG11对应的几位设置成AF6,把PB2对应的几位设置成AF8即可,至此GPIO口的uart4复用功能就实现了。

【UART模块设置】

对uart模块的设置相对繁琐,具体分为以下几步:

1、设置数据长度为8

2、设置16位过采样

3、设置不需要校验位

4、设置1位停止位

5、设置不分频

6、设置波特率

7、对发送器、接收器、串口分别进行使能

对上面三张图的寄存器的对应位进行修改即可实现上述七个步骤。

值得一提的是在对BRR进行波特率设置的时候可以通过直接赋值的方式直接设置波特率,但是这个需要设置的值收到过采样频率的影响,由于8倍的过采样频率过于复杂,本次实验采用16倍采样频率,具体公式如下:

设置值 = 模块工作频率(HZ)/ 要设置的波特率(bit/s)

对uart模块进行读写操作的步骤

1、判断是否有数据需要读取或写入(对USART_ISR寄存器相应的位进行判断)

2、将需要读取的数据放入读取寄存器中(数据会存储在USART_RDR寄存器等待用户读取)

3、将需要发送的数据放入写寄存器中(将数据直接写入USART_TDR寄存器即可发送数据)

【代码】

在了解了以上串口工作原理之后就可以开始编写代码了。本次代码结合了昨天的led模块,实现了串口对灯的控制。具体功能见视频:

https://blink.csdn.net/details/1666295?spm=1001.2014.3001.5501

具体代码如下:

main.c

#include "uart4.h"#include "led.h"void delay(int ms){int i,j;for(i=ms;i>0;i--){for(j=2000;j>0;j--){}}}int main(){uart4_init();led_init();// char i;char buf[30];while(1){// i = getchar();// putchar(i + 1);gets(buf);if(strcmp(buf,"led1 on")==0){led1_on();puts("exec success\r\n");}else if(strcmp(buf,"led1 off")==0){led1_off();puts("exec success\r\n");}else if (strcmp(buf, "led2 on") == 0){led2_on();puts("exec success\r\n");}else if (strcmp(buf, "led2 off") == 0){led2_off();puts("exec success\r\n");}else if (strcmp(buf, "led3 on") == 0){led3_on();puts("exec success\r\n");}else if (strcmp(buf, "led3 off") == 0){led3_off();puts("exec success\r\n");}else{puts("error cmd\r\n");}}return 0;}

uart4.c

#include "uart4.h"void uart4_init()
{//使能GPIOB,GPIOG,UART4RCC->MP_AHB4ENSETR |= (0x1 << 1);RCC->MP_AHB4ENSETR |= (0x1 << 6);RCC->MP_APB1ENSETR |= (0x1 << 16);//设置pb2和pg11的管脚复用pb2/pg11GPIOB->MODER &= ~(0x3 << 4);GPIOG->MODER &= ~(0x3 << 22);GPIOB->MODER |= (0x1 << 5);GPIOG->MODER |= (0x3 << 23);GPIOB->AFRL &= ~(0xf << 8);GPIOB->AFRL |= (0x1 << 11);GPIOG->AFRH &= ~(0xf << 12);GPIOG->AFRH |= (0x3 << 13);//设置串口不使能,ue=0USART4->CR1 &= (~(0x1));//设置8位数据位USART4->CR1 &= (~(0x1 << 12));USART4->CR1 &= (~(0x1 << 28));//设置没有奇偶校验位USART4->CR1 &= (~(0x1 << 10));//设置1位停止位USART4->CR2 &= (~(0x3 << 12));//设置16倍过采样USART4->CR1 &= (~(0x1 << 15));//设置时钟不分频USART4->PRESC &= (~(0xf));//设置波特率为115200USART4->BRR = 0x22b;//使能发送器USART4->CR1 |= (0x1 << 3);//使能接收器USART4->CR1 |= (0x1 << 2);//使能uart4USART4->CR1 |= (0x1);
}void putchar(char a)
{//先判断发送寄存器是否为空while(!(USART4->ISR & 0x1<<7)); //取出第七位的数据,如果是1表示 当前寄存器为空USART4->TDR = a;//不为空阻塞等待//为空向寄存器中写入数据//写入完成判断发送是否完成,未完成阻塞,完成函数结束while (!(USART4->ISR & 0x1 << 6));
}char getchar()
{//判断接收寄存器中是否有数据有数据读取,没数据阻塞//读取成功返回该字符char a;while (!(USART4->ISR & 0x1 << 5));a = USART4->RDR;return a;
}void puts(char *s)
{while(*s){putchar(*s);s++;}putchar('\r');putchar('\n');
}void gets(char *s)
{while(1){*s = getchar();putchar(*s);if (*s == '\r'){break;}s++;}*s = '\0';
}int strcmp(char *src,char *dest)
{char *p = src, *q = dest;while(*p==*q&&*p!='\0'&&*q!='\0'){p++;q++;}if(*p>*q){return 1;}else if(*p<*q){return -1;}else {return 0;}
}

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

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

相关文章

array go 语言的数组 /切片

内存地址通过& package mainimport "fmt"func main() {var arr [2][3]int16fmt.Println(arr)fmt.Printf("arr的地址是: %p \n", &arr)fmt.Printf("arr[0]的地址是 %p \n", &arr[0])fmt.Printf("arr[0][0]的地址是 %p \n"…

动态规划Dynamic Programming

上篇文章我们简单入门了动态规划&#xff08;一般都是简单的上楼梯&#xff0c;分析数据等问题&#xff09;点我跳转&#xff0c;今天给大家带来的是路径问题&#xff0c;相对于上一篇在一维中摸爬滚打&#xff0c;这次就要上升到二维解决问题&#xff0c;但都用的是动态规划思…

手机termux上用hydra在线暴力穷举破解

HYDRA 是一个在线暴力破解工具&#xff0c;速度快&#xff0c;穷举稳定&#xff0c;支持50线程的暴力穷举破解&#xff0c;兼容的协议也多&#xff0c;telnet, ftp, http, https, smb, 多数网页服务的databases&#xff0c;应用广泛。 在手机termux上也可以轻松实现。 不废话…

开源博客项目Blog .NET Core源码学习(10:App.Framwork项目结构分析)

开源博客项目Blog的解决方案总共包括4个项目&#xff0c;其中App.Hosting项目包括所有的页面及控制器类&#xff0c;其它项目主要提供数据库访问、基础类型定义等。这四个项目的依赖关系如下图所示&#xff0c;本文主要分析App.Framwork项目的主要结构及主要文件的用途。   …

150 Linux C++ 通讯架构实战6 服务器程序目录规划,通过vs2017实现文件夹的创建,makefile编写

从无到有产生这套 通讯架构源代码【项目/工程】 一&#xff0c;服务器程序目录规划 一个完整的项目 肯定会有多个源文件&#xff0c;头文件&#xff0c;会分别存放到多个目录&#xff1b; 我们这里要规划项目的目录结构&#xff1b; 注意&#xff1a;不固安是目录还是文件&am…

水瓶座性格分析及星座配对!

水瓶座性格分析及星座配对&#xff01; 标签&#xff1a;水瓶座 水&#xff0f;瓶&#xff0f;座 1.20~2.18 “珍爱生命&#xff0c;远离水瓶” 这是一个被水瓶座折磨的巨蟹文艺男青年的呐喊 “都是外星人&#xff0c;根本没法沟通” 这是号称水瓶最佳基友的逆生长射手妹子…

21.同步模式-保护性暂停

1.Guarded Suspension,用在一个线程等待另一个线程的执行结果。 2.一个结果从一个线程传递到另一个线程&#xff0c;让他们关联同一个GuardedObject 保护对象。 3.如果有结果不断从一个线程到另一个线程&#xff0c;那么可以使用消息队列。 4.join方法和Future的实现&#x…

JavaScript原型、原型对象、原型链系列详解(三)

(三)、JavaScript原型链 原型链 在 JavaScript 中&#xff0c;对象之间的继承是通过原型链来实现的。每个对象都有一个指向原型对象的内部链接&#xff0c;也就是 [[Prototype]] 属性。这个链接的作用是如果对象本身没有某个属性或方法&#xff0c;就会去它的原型对象上找&…

Linux 进程通信:匿名管道、实现进程池

目录 一、进程间通信 1、 为什么需要进程通信 2、发展和分类 二、管道 1、概念 2、特点 2、复制并共享 3、用fork来共享管道原理 4、站在文件描述符角度-深度理解管道 5、站在内核角度-管道本质 三、匿名管道 1、概念 2、创建 3、snprintf 4、父子进程中进行单…

小程序英文口语发音评测

一、英文口语评测需求 在全球化的今天&#xff0c;英语已经成为了世界上最重要的国际语言之一。无论是在国际商务、科技研究、教育还是日常生活中&#xff0c;英语都扮演着举足轻重的角色。因此&#xff0c;掌握英文口语的能力对于个人的职业发展、学术研究以及跨文化交流都具…

【Linux】vim配置及安装方法

注 安装方法在文章最后 配置文件的位置 在目录 /etc/ 下面&#xff0c;有个名为vimrc的文件&#xff0c;这是系统中公共的vim配置文件&#xff0c;对所有用户都有效。而在每个用户的主目录下&#xff0c;都可以自己建立私有的配置文件&#xff0c;命名为“.vimrc”。例如&…

蔚来-安全开发一面/二面

基本不怎么会渗透测试&#xff0c;本科期间有过大数据隐私保护(密码)的项目&#xff0c;硕士期间有个华为合作的项目一篇在投的ai安全论文 一面&#xff08;45min&#xff09; 1.介绍自己 2.介绍一下实习 3.场景题轰炸&#xff0c;主要针对实习中的场景&#xff0c;主要考察…

atoi函数详解

atoi函数使用方法 在c官网中是这样介绍atoi函数的 通俗的讲就是把字符串中的字符数字转换为整形数字&#xff0c;遇到空格就跳过&#xff0c;如果在字符串开始遇到不是有效的整数比如说abc就直接返回0&#xff0c;如果遇到像这种情况123abc345这个就只返回123&#xff0c;这个…

Prometheus监控数据格式的学习

文章目录 Prometheus metrics概念数据类型数据形式 Prometheus metrics概念 Prometheus监控中metrics是对采集数据的总称。指标数据通常包括名称、标签、值和时间戳等信息。通过Prometheus metrics&#xff0c;用户可以更好地了解应用程序和系统的性能表现&#xff0c;以便进行…

Oracle AI Vector Search Multi-Vector Similarity Search 即多向量相似度检索学习笔记

Oracle AI Vector Search Multi-Vector Similarity Search 即多向量相似度检索学习笔记 0. 什么是多向量相似度检索1. 多向量相似度检索的示例 SQL2. 执行多向量相似度检索3. 分区行限制子句的完整语法 0. 什么是多向量相似度检索 多向量相似度检索涉及通过使用称为分区的分组…

【openGL4.x手册07】几何着色器

目录 一、说明二、关于几何着色器三、原始输入/输出规范3.1 实例 四、输入五、输出5.1 分层渲染 六、输出限制 一、说明 几何着色器对于渲染管线设计是一个新生事物&#xff1b;目前对应于几何着色器的资料不多&#xff0c;并且说法不一&#xff0c;因此如何用几何着色器&…

C语言数据结构之计数排序

世中逢尔 雨中逢花 目录 计数排序的介绍 代码展示 时间复杂度和空间父复杂度 计数排序的用途 计数排序的局限性 计数排序的介绍 排序原理 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用。 是一个不比较排序算法&#xff0c;通过计数将时间复杂度降到了O…

大型网站集群管理负载均衡

课程介绍 结合企业大规模应用&#xff0c;解决应用高并发问题&#xff0c;解决单节点故障问题&#xff0c;缓存数据库的应用。学完掌握知识点&#xff1a;企业应用实现四七层负载均衡&#xff0c;以及Nginx等应用的高可用性&#xff0c;Redis缓存数据库的部署应用以及高可用方…

Python 如何设置和读取 config.ini 文件

当你开始编写Python应用程序时&#xff0c;通常需要一种方法来配置应用程序的设置&#xff0c;如数据库连接信息、API密钥等。使用配置文件是一种常见的方法&#xff0c;而INI文件是一种简单而常见的配置文件格式。在本文中&#xff0c;我将介绍如何使用Python设置和读取INI格式…

中国联通的DDoS攻击防护解决方案

DDoS防护&#xff1a;打造坚不可摧的在线业务护城河 在当今瞬息万变的数字世界中&#xff0c;企业的在线服务与应用已成为业务运作的核心&#xff0c;而这也使其面临日益严峻的安全挑战&#xff0c;尤其是分布式拒绝服务&#xff08;DDoS&#xff09;攻击&#xff0c;它能短时…