自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(37)
  • 收藏
  • 关注

原创 FreeRTOS 队列

因为同一个队列可以被多个任务读取,因此可能会有多个任务因等待同一个队列,而被阻 塞,在这种情况下,如果队列中有可用的消息,那么也只有一个任务会被解除阻塞并读取到消 息,并且会按照阻塞的先后和任务的优先级,决定应该解除哪一个队列读取阻塞任务。当想某一个队列写入数据时,如果此时的队列已经满了,就是没有空位置了,这时任务实际上是阻塞住了,因为想要写入但是无法写入,我们可以设定一个等待阻塞时间,等待的时间在设定范围内,任务就会被添加到阻塞列表中进行等待,等待队列中有空位置。uxItemSize就是队列项目的大小。

2024-07-11 17:56:49 858

原创 FreeRTOS 列表和列表项

通常情 况下,处于阻塞态的任务都有一个阻塞的超时时间,在任务阻塞达到或超过这个超时时间后, 即使任务等待的外部事件还没有发生,这里所说的列表和列表项,是 FreeRTOS 源码中 List 和 List Item 的 直译,事实上,FreeRTOS 中的列表和列表项就是数据结构中的链表和节点。实际上,当FreeRTOS有很多列表,包括就绪列表,阻塞列表,挂起列表等,结合上面的解释就知道了,处于就绪态的若干任务放在就绪列表,处于挂起态的若干任务放在挂起列表等。四种任务状态之间的转换图如下图所示。

2024-07-08 18:55:25 127

原创 FreeRTOS 任务

通过前面的图可以知道,任务是相互切换完成执行的,A任务切换到B任务的时候,CPU从接管A任务的状态切换到接管B任务的装填,那么就需要对A任务的当前现场进行保护,在下次再进行A任务的时候再恢复现场,这里说的保护和恢复,实际上是针对A任务中的一些变量进行的,所以A任务需要一个堆栈,同理,B任务也需要一个自己的堆栈。注意,任务的堆栈这里给的是Depth也就是深度,个人理解实际的大小是深度×宽度,宽度就是事先定义好的字的长度,,那么实际的堆栈大小就是usStackDepth*一个字的字节。

2024-07-06 10:10:36 569

原创 STM32学习-HAL库 定时器

HAL_XXX_MspInit()这种是外设硬件相关的初始化函数,包括GPIO,NVIC,CLOCK等,一般会在HAL_XXX_Init()中调用。定时器涉及的结构体主要有两个,TIM_HandleTypeDef和TIM_Base_InitTypeDef具体参数如下,使用HAL_TIM_Base_Init()函数初始化定时器,并且在该函数内部会调用HAL_TIM_Base_MspInit()初始化外设硬件。开启定时器也有很多方式,轮询方式,更新方式,DMA方式等,HAL库中有相对应的开启和停止函数。

2024-06-25 19:11:21 263

原创 STM32学习-HAL库 串口通信

串口的主要功能就是接收和发送HAL_UART_Transmit和HAL_UART_Receive都是阻塞方式发送和接收,执行完之后就不再执行,还阻碍了其他代码的运行。一般使用中断方式进行收发,涉及的比较复杂,HAL_UART_Receive_IT()和HAL_UART_Transmit_IT()这里给出接收的图解。学完标准库之后,本来想学习freertos的,但是看了很多教程都是移植的HAL库程序,这里再学习一些HAL库的内容,有了基础这里直接学习主要的外设。发送和接收类似,不再赘述。

2024-06-25 11:39:49 969

原创 STM32学习 修改系统主频

可以看到这个文档里面给出了一些宏定义,这个就是系统的频率,选定哪个,就是设定哪个频率,这里就以72MHZ为例子看是如何配置时钟的,在文档中搜索一些使用到72MHZ的地方。前面时钟树的学习说明单片机的主频是可以修改的,那么怎么更改系统的主频,这里做一个简单的介绍。最终调用SystemInit()完成时钟的配置,所以只要在宏定义处使用官方配置好的一些就行,如果想要自己定义,就要重新编写寄存器相关的操作。使用的F103系列的引脚是GPIOD,所以可以看到使用寄存器的方式配置了相关的引脚,能够使用外部晶振。

2024-06-23 20:18:03 1061

原创 STM32学习 时钟树

下面在HSE和其2分频中选一个通入到上面,再和HSI 的2分频进行选择,之后PLLMUL就是倍频,为什么要倍频,可以看到后面的SYSCLK最大是72Mhz,但是HSI和HSE最大也就是8Mhz,倍频就是把频率增加,可以看到PLLMU有多种选择,x2,x4最多是16倍倍频,具体使用哪一个需要我们在代码里面配置。再来看后面的框图,可以看到AHB,AHB就是先进高性能总线,在AHB总线上有一条时钟线HCLK,这条时钟线就连接到DMA,内存,CPU等,其中系统时钟就是系统滴答时钟。这是最底层的时钟来源。

2024-06-18 17:51:51 816

原创 STM32学习 BKP

下面是手册当中的描述。后面两句话是在设定TPE位之前如果TPAL的引脚电平并不符合所设定的侵入条件(比如选定上升沿侵入但此时引脚已经是高电平无法产生上升沿),那么在设定TPE位之后会自动产生一个侵入事件,这个就会直接复位备份寄存器的内容,所以在启动前要保持正确的TAMPER电平你,防止启动之后自动触发。这里可以看到,TPAL=0,就是上升沿为侵入事件,TPAL=1,就是下降沿为侵入事件。在引脚图上可以看到,TAMPE,RTC都是在PC13引脚上,VBAT也就是备份电源是单独的引脚,这个就是芯片的1号引脚。

2024-06-16 13:26:22 337

原创 STM32学习 SPI通信

同时,从机也会把从机的移位寄存器中的数据一位一位的通过MISO线发送给主机,也就是收发是一起的,在发送的同时也在接收,如图所示。在指定地址读时,先是主机向从机进行有效字节的交换,从机可以拿无效字节进行交换,也就是指令+地址,之后就是从机向主机进行有效字节(读入的数据)的交换,主机可以拿无效字节进行交换。CPOL=0,空闲模式时SCLK为低电平,也就是说,当开始传数据时,SCLK发出脉冲信号时,要从低电平先变为高电平,那么第一个边沿就是上升沿,第二个边沿就是下降沿。这个地址和数据可能是多个字节,分多次传输。

2024-06-14 18:19:27 679

原创 Ubuntu侧边任务栏更换位置的方法

切换到底部,在终端输入。

2024-06-10 20:03:31 94

原创 Linux 安装QT踩坑-填坑

这里使用的是Ubuntu的16.04.7的系统,在这里搜到到了QT4,于是安装了qt4.6.0的远古版本。不同版本的LINUX系统安装不同版本的QT会出现差异性,最好只安装对应的版本。权限不够就切换到root下.注意,不使用QT的账户就必须先断开网再进行安装。ps:也试了最新的,查了很多博客也还是不会,干脆使用旧的版本吧。下载对应的安装包,选linux的X86_64的安装包。此时的安装包没有安装权限,在终端里按顺序执行以下命令。下面这个文章是对官网的一个说明。首先进入QT 的官网。

2024-06-02 14:58:55 175

原创 STM32学习 I2C通信

I2C通信很常用,是同步的半双工通信,一根SCL(时钟线),一根SDA(数据线)。多主多从的模式,任何一个模块都可以主动跳出来担当主机的角色,当然,首先该模块能才行(比如单片机可以当从机也可以当主机),但是同一时刻只能有一个主机,当冲突时,会进行仲裁,多主机的情况下,要进行时钟同步。这里通俗的理解一下,个人理解时钟的控制权就是只有主机才能决定在哪一个时刻进行通信,从机只能等待,当进行通信时的时刻到来时,从机就会被动的在这个时刻接收来自主机的指令,并且接收到以后需要进行应答。重复8次就能完成一个字节的。

2024-06-01 20:12:26 400

原创 STM32学习 串口通信

中间这一块是发送控制和接收控制,下面还有中断控制,通向NVIC,最下面是波特率发送器,可以看到fpclk,这个就是挂载的时钟总线的时钟,选定之后除一个分频系数USARTDIV,这个实在右边进行设置的,分为整数部分和小数部分,具体看数据手册中的描绘。起始位的检测是在一位的时间长度内进行多次采样,当经过3个采样时钟为3个1,后一个为0时,即检测到了下降沿,之后在一位的时间内进行16次采样,如果发现多个0(这里详细看手册的描述)那么便认为是起始位0,如果条件不符合那么就抛弃前面的数据,等待新一轮的起始位检测。

2024-05-28 16:48:17 450

原创 STM32学习 通信相关基本概念

这里通俗的解释一下码元,码元就是一个脉冲信号,但是这个脉冲信号可能携带多个bit的数据,可能1,可能2等。官方点就是4种不同的振幅或者频率或者相位,因为实际的信息传输都是用振幅,频率,相位等来表示信息的。码元说白了就是你以怎样的形式去定义你要发的信息,传输多个bit,还是一个码元。比特率=波特率*log2(M),这个公示也就很好解释了,每秒传输的码元数*每个码元的bit数=每秒传输的bit数。异步通信:没有时钟信号,他通过在数据前后加入起始位或者终止位,通过纠错编码,解码等方式保证数据正确性。

2024-05-24 14:16:08 268

原创 STM32学习 DMA(2)-原理和使用

看上面的图,左侧就是M3内核和DMA,这实际上是主动单元,右边的外设寄存器(存储器),SRAM,Flash等,本质都是存储器,是被动单元,左侧的可以访问右侧的,但是右侧的只能被左侧的读写。这里看这个列表,如果源地址的起始地址是p1,选择自增的话,在传输完毕后,地址会自动加1转到p2,接收同理,目标地址的起始地址是q1,选择自增的话,在接收完毕后,地址会自动加1转到q2。传输计数器就是设定转运次数的,每转运一次,这个数就会减一,当减到0时,转运就会停止,同时增加的地址会恢复到最开始的起始地址。

2024-05-21 23:05:08 573

原创 STM32学习 DMA(1)-寄存器和存储结构

这里就可以看到,SR,CR1,CR2等就是ADC1中的寄存器了,其中每个寄存器的大小就是定义的32位int型的数据,通过前面c语言的学习也知道,实际上结构体成员变量是按照顺序存储的,所以直接访问每个成员变量就是在访问相对应地址的内存地址,这和手册上的寄存器映像中各个寄存器的地址顺序也对应。在库函数中,是在stm32f10x.h文件中,外设资源是挂载再时钟总线上的,所以要先找到时钟总线的地址再进行计算,这里可以看到各个寄存器前面有一个偏移值,实际的内存地址就是基址+偏移量。其他的和上面所述类似,不再赘述。

2024-05-18 21:59:17 411

原创 STM32学习 ADC

这里规则组可以理解成一个菜单,菜单上有16个菜(通道),然后按照点菜顺序(通道的序列号顺序)做好(进行转换),然后一次性给你所有数据,但是有个问题,可以看到规则组的数据寄存器只有一个,这里可以理解你的桌子只能放下一个菜,一次性给你所有的菜(数据),但是存储完一个不及时处理的话,那么就会被下一个数据覆盖掉,所以规则组通常配合DMA一起使用,在给你一个数据后及时进行转移避免覆盖。再下面可以ADC的控制,也是分为注入组的触发控制位和规则组的触发控制位,注意这里的是硬件触发源,也可以使用软件触发。

2024-05-17 18:21:11 547

原创 STM32学习 定时器

这张图其实很清晰的说明了基本定时器的功能,所谓定时,就要有一个基准的时间,这个时间也就是频率,当某一基准时间*计数次数=设定的时间时就完成了定时功能,举例就是假设定一个40s的时间,1s记一次要计数40次,2s记一次要计数20次,4s记一次要计数10次,就是面多加水,水多加面,当然这个定时的最大范围时有限制的,那怎么去增加?定时器套定时器就可以了。这就需要自动重装寄存器,它就存储着我们的计数目标,是固定的,达到时,产生一个中断(也就是定时器中断,要使用NVIC,前面涉及过)或者事件,再进行下一轮。

2024-05-10 19:26:48 196

原创 STM32学习 外设资源及AFIO

比如下面这个 如果想同时使用串口1和定时器1的功能,发现二者功能复用在了相同的引脚上,这就发生了冲突,但通过手册可以知道,我们可以把串口1的功能映射到别的引脚上 这里是PA_10,PA_9 -->PB_6,PB_7,这样配置就可以同时使用。另外 AFIO在配置外部中断时依然使用,可以理解成一个数据选择器,让唯一的引脚号去到外部中断通道,其实也可以理解成"映射",16个当中的1个映射到外部中断通道中。stm32系列包含有很多外设,定时器,gpio,外部中断,adc,usb等。

2024-05-09 17:15:04 198

原创 STM32学习 中断

比如图示这个,如果B和C同时申请中断,二者的抢占优先级相同,B的响应优先级更高,所以先响应B再响应C;抢占,就是再在A中断处理过程中突然出现B中断抢夺A的位置执行,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断。使用的中断设置分组方式,可以用4位进行设置,这4位进行切分,分为高n位的抢占优先级和低4-n位的响应优先级。第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级。第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级。第4组:所有4位用于指定抢占式优先级。

2024-05-07 22:20:40 330

原创 STM32学习 GPIO

这是init函数的介绍,两个参数,第一个是引脚的通道选择,第二个是一个指向结构体的指针,也就是传入指针,复杂数据通过指针传入函数,这个前面讲过。gpio初始化实际上是用的结构体数据类型GPIO_InitTypeDef进行初始化,这是它的成员变量 其中各个变量使用的是枚举变量来表示整数,应该就是向寄存器写入的值。GPIO使用时先进行初始化,设置输入输出模式,再进行读写。这里先进行时钟线的配置使能。

2024-05-06 20:46:20 217

原创 C语言学习 静态本地变量

这里在f()函数的内部定义了int型的变量all,并用static进行声明,这里实际上是创建了一个全局变量all,只在第一次执行时初始化一次,在函数结束时,依然存在,依然保持函数结束后的值,后面不进行初始化了,但是只能在所定义的函数内部使用。说明all在这里起着全局变量的作用,但是只能在f()内部进行只有,只有局部作用域,在main()函数里面无法进行使用,并且查询地址发现all和k并不在一起,实际上挂在了全局变量的地址内,也就是内存地址是全局的。

2024-05-04 11:52:26 146

原创 C语言学习 枚举和结构体

这里声明了一个枚举类型,允许enum color作为一个类型名应用,在第二行使用t创建了该类型的变量,在第一个声明中使用标识符枚举了color所有可能的值,可能是red,yellow或者blue,这成为枚举符。,一个结构就是一个复合的数据类型,在里面可以有各种类型的成员,可以是char 可以是int 可以是float等等,我们用一个变量来表达,并且各个成员变量相互独立。但是,枚举只能在程序内部使用,比如要输入color中red的值,只能输入1而不是单词red,或者读入字符串"red"再转换为其他值。

2024-05-03 18:49:29 222

原创 C语言学习 字符串的函数

注意"A"和'A'是不同的,前面是char[2]字符串 后面是char字符。如果相同所引的s1排在s2的前面 返回-1 反之返回1。当然这里也可能打印处-32 因为结果和不同的编译器有关。字符串本质就是数组 直接比较是比较的地址。注意 这里实际上是按字符串的顺序比较。可以理解为s1[i]-s2[i]并且字符串不能直接比较 因为。函数的返回值是1 0 -1。对应的ascii码值,

2024-04-29 12:04:09 100

原创 C语言学习 字符串补充getchar()和putchar()

getchar()函数实际上是int getchar(void),所以它返回的是ASCII码,所以只要是ASCII码表里有的字符它都能读取出来。在调用getchar()函数时,编译器会依次读取用户键入缓存区的一个字符(注意这里只读取一个字符,如果缓存区有多个字符,那么将会读取上一次被读取字符的下一个字符),如果这个是回车,那么也会读到,如果缓存区没有用户键入的字符,那么编译器会等待用户键入并回车后再执行下一步 (注意键入后的回车键也算一个字符,输出时直接换行)。getchar()则会把回车作为字符都进来。

2024-04-28 21:30:37 114

原创 C语言学习 字符串

程序的 s 属于初始化变量,s 如果是局部变量则指向栈上的内存区域,如果是 static 或全局变量则指向进程的。这两段的程序中 "hello, world" 是一个字符串面量,str 的确指向其地址,但该地址存在进程的。本质就是有没有终止符,0标志这字符串的结束,但是它不是字符串的一部分,计算这段字符串的长度时不包含这个0。字符串以数组的形式存在,以数组或指针的形式访问。段除了保存常量还保存可执行代码,因此是。段,代码段,字符串常量池,

2024-04-27 18:57:52 197

原创 C语言学习 指针和const

当传递的参数类型很大时,比如结构体,这时候可以传入它的地址,使用常量指针这样就可以用较少的字节完成值的传递但不改变外面变量的值。指针这种变量实际上包含两个东西,一个是指针本身(也就是某个地址),一个是指针所指向的那个变量(地址所存的变量)。//指针变量p指向int i,并且p的值是一个不能改变的常量,也就是i的地址。指针所指的是const,表示不能通过这个指针取修改那个变量(但并不能是那个变量成为const)指针是const,表示一旦获得了某个变量的地址,不能再指向其他的变量了(指针常量)

2024-04-23 18:51:50 275

原创 C语言学习 指针和数组

数组变量是特殊的指针,因为数组变量本身就表达地址,在取地址的时候可以看到在取数组的地址可以不需要加&符号,直接拿数组变量的名字就可以得到数组的地址,但数组的单元表达的是单个的变量,需要&符号。[]可以对数组做,也可以对指针做。数组变量是const常量指针,不能被赋值,不能等于另外一个数组,也就是说数组变量是一段固定的地址。int a[10] 定义了一个数组变量a,有一段连续的内存空间 这段空间存有10个int型的数组。可以看到 数组的地址==数组变量本身==数组首元素的地址。

2024-04-22 19:18:42 190

原创 C语言学习 指针

星号可以远离int也可以靠近int,他们都表示说定义了一个指向int的指针变量p和一个int型的变量q,所以可以说并不是把星号加给了int 而是加给了p。函数调用的时候参数的传入是一种值的传递,把值传进了函数,和原来的地方没有任何的联系,传入地址时仍然时值的传递,但通过这个地址,可以访问到原来的变量进行读写。这里*表明p就是一个指针 p保存的东西就是i的地址 int 说明指向的是一个int。指针变量的值就是内存的地址,普通变量的值是实际的值,指针变量的值是具有实际值的变量的地址。指针就是保存变量的地址。

2024-04-21 18:02:31 223 1

原创 C语言学习 逃逸字符(转义字符)

制表位才能使上下行对齐这个符号的位置在行当中是固定的 而不是固定的长度 当字符长度为到达一个制表长度而未到达第二个 占据第二个 当字符长度超过一个长度而未超过两个长度 占据第三个。只有当\b后面存在字符时(空格也算时)才有效 效果时前面的字符消失 后面的补上。\r就是单独的回车 直接移动到最前面 后面有个空格多占一个位置。\t制表符 是将该符号后面的字符移动到下一个制表符号tab处。\n实际上是回车+换行。

2024-04-15 17:39:42 129 1

原创 linux运行汇编的两种方式

linux可以使用nasm和gas编译运行汇编。使用nasm编译汇编文件(.asm和.s都行)使用ld命令链接目标文件并生成可执行文件。使用ld命令链接目标文件并生成可执行文件。nasm一般编译Intel风格的汇编。gas一般编译AT&T风格的汇编。使用as命令编译汇编文件。运行生成的可执行文件。运行生成的可执行文件。

2024-04-09 21:30:37 254 1

原创 C语言学习 输入和输出

格式控制字符串里的转义字符按照转义后的含义输出,如上面printf函数双引号内的换行符“\n”,即输出回车。普通字符即需要在输出时原样输出的字符,如上面printf函数中双引号内的“f=”和“c= ”部分。格式字符由“%”引导,如%d、%f等。它的作用是控制输出字符的格式。例如 printf("f=%f,c=%f\n",f,c);对于字节低的char和short 格式化输出会扩展位数。c语言中输出是printf()一般格式是printf(格式控制。

2024-04-08 17:08:11 226

原创 c语言学习 基本数据类型

1个字节(Byte)时8位二进制比特位(bits) 计算机储存数据都是以补码进行存储的 一般用sizeof()对数据类型进行内存长度的测量(单位是字节)整型 int(4个字节) char(1个字节) long(4个字节) long long(8个字节)对于unsigned * 类型(无符号) 只是解释的方式变了 内存空间大小还是不变的。注意 在windows或linux的不同位数系统下所占的内存空间可能会不同。浮点型 float(4个字节) double(8个字节)注意 计算机是以补码进行储存数据的。

2024-04-07 17:58:49 97

原创 c语言练习 整数分解

【代码】c语言练习 整数分解。

2024-04-05 17:30:56 99

原创 c语言学习break和continue

例如输入的x=6 此时i=2<x 进入循环 但是6%2==0 让a=0 遇到break语句,直接跳出for循环 剩下的循环也不做了 在当前的循环的位置直接跳出。遇到continue时,continue后面的语句不做了,跳过这一轮的循环,进入到下一轮。遇到break语句时直接跳出循环,剩下的循环也不做了。

2024-04-05 14:51:46 194 1

原创 C语言学习for循环

在第一次进入for循环时i=1,进行判断和x进行比较,但时此时的i并不进行+1操作,只有进入第二次循环的时候i才进行步进操作(加减乘除)+1或者-1;i++)或者for(...;i--)或者for(...;第二次判断时i=1,并进行i++操作 i=2,i

2024-04-05 13:49:01 184 1

原创 bmp位图图像处理

学习记录。

2023-11-03 19:07:56 41

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除