- 博客(18)
- 收藏
- 关注
原创 设计一个嵌入式设备日志记录模块
设备开机或者复位都会进行导入系统日志参数操作,恢复日志读写参数,参数区为频繁读写操作区域,每一次写操作都会进行一次偏移,有效的导入参数方法是从参数区结束地址到起始地址进行扫描,扫描不到合法的参数则会导入默认日志参数。实际实现会定义最新的目录信息存储在日志参数区,当日期发生改变,则表示当前目录信息已经完结,将最新的目录信息录入日志目录区保存,最多每天写入一次目录区。设置与读取应用调试等级由读者自行定义。:根据日期进行归类,记录当天的日志的存储地址、日志索引、日志大小,通过目录可以获取整个日志文件的概况;
2025-02-06 14:23:02
835
原创 STM32F103ZET6实现蜂鸣器音量大小的设置
使能GPIOB端口的时钟,因为TIM4的CH3复用输出连接到GPIOB的第8脚(PB8)这里,需要用到复用功能I/O和调试配置(AFIO),STM32F1XX参考手册的116页有对应的映射功能表,118-119页的定时器复用功能重映射表则标明了PB8的映射目的地为TIM4定时器的CH3通道。GPIO控制器只能通过软件输出高低电平来控制电流的开关,并不能控制输出的电平大小,因此不能通过直接操作GPIO控制器来控制BEEP蜂鸣器的音量大小。通过设置比较寄存器的值,改变PWM信号的占空比,控制输出的电平高低)
2024-12-27 16:49:08
868
原创 linux内核延时的方法
而有些场合,等待某个事件满足要求,这个事件满足要求可能是随机的,可能随时就能满足你的要求,那么此时就需要立刻唤醒休眠的进程并且让它正常运行处理到来的时间。schedule_timeout(5) // 休眠等待50ms,事件单位是硬件定时器中断触发的次数。休眠等待只能用于进程,不能用于中断,进程休眠是指进程会释放掉占用的CPU资源给其他进程使用。例如:msleep(500) // 进程休眠等待500毫秒。例如:mdelay(10) // CPU原地空转10毫秒。
2024-12-14 16:46:21
786
原创 嵌入式Linux内核等待队列机制
如果发现数据没有准备就绪,那么可以让进程在底层驱动的read或者ioctl接口函数中进行等待操作,此等待必然使用休眠等待,如果让进程休眠等待,又不能调用msleep/ssleep/schedule/schedule_timeout这些函数,因为这些函数虽然可以让进程进行休眠等待,但是当数据准备好时不能随时唤醒进程,并且正常运行(休眠没结束来数据了,怎么办?一旦进程被唤醒,进程就可以读取接收到的数据并且将数据拷贝到用户缓冲区然后返回即可,至此应用程序的read或者ioctl函数完成数据的一次读取操作。
2024-12-13 21:06:17
786
原创 嵌入式驱动程序中,软件实现按键去抖的方式
软件消抖有个更高级版,逻辑上是增加一个定时器,把原本在中断处理函数中要实现的逻辑功能,放到定时器的超时处理函数当中,而中断处理函数中则重新设置新的定时器(mod_timer(&定时器对象,新的超时时间)),在触发超时处理函数前重新计时,这样的话每次抖动(高低电平变化)都会在定时器倒计时为0前重新设置定时器,而当抖动停止,电平稳定之后,定时器就能走到0触发超时处理函数,实现原本的逻辑(因此定时器应该在申请中断资源前完成初始化)机械按键在按下或松开时,由于接触面积和时间的问题,会产生一个不稳定的信号。
2024-12-12 19:42:36
442
原创 3.stm32常用库函数(GPIO)
第一个参数指对应GPIO的时钟(在STM32中操作GPIO前,需要先使能该GPIO端口对应的时钟。通过RCC寄存器对GPIO时钟使能——>通过GPIO_InitTypeDef配置GPIO参数——>通过GPIO_Init初始化GPIO控制器——>输出高低电平。根据形参类型可以看出,GPIOx就是指上文中对应GPIO控制器的地址,GPIO_InitStruct指上文中GPIO控制器配置参数的结构体。GPIO控制器初始化时配置参数的结构体:GPIO_InitTypeDef。总头文件:stm32f10x.h。
2024-12-05 09:21:18
477
原创 2.STM32F103ZET6的GPIO和位操作
推挽复用输出:GPIO_Mode_AF_PP:输出高电平时,电流输出到负载,叫灌电流,可以理解成推,输出低电平时,负载电流流向芯片,叫拉电流,即挽(用于UART控制器)推挽输出:GPIO_Mode_Out_PP:输出高电平时,电流输出到负载,叫灌电流,可以理解成推,输出低电平时,负载电流流向芯片,叫拉电流,即挽(用于GPIO控制器)开漏输出:GPIO_Mode_Out_OD:只能输出低电平,输出低电平,N-MOS导通,如果输出高电平需要外接上拉电阻(用于GPIO控制器)
2024-12-04 10:05:34
900
原创 1.嵌入式stm32的基本概念
控制外设 : 键盘输入:'A' ---读read---> CPU ---写write---> 显示器:'A'开发环境1:Windows系统 + Keil5开发工具(编辑、编译、下载、调试代码)(最终基于单片机的可执行文件只有一个)将 A 的 6,7,8位清0 : A &= ~(0x7
2024-12-03 09:20:32
313
原创 常用的几种文件操作函数
返回值一般不关注,FILE* stream指要操作的文件指针,const char* format与printf函数的第一个形参相同,[argument]与printf函数的第二个形参相同。函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);函数原型:size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
2024-08-09 21:04:29
1434
原创 动态内存分布函数(malloc、calloc、realloc、free)
接收一个void*和一个unsigned int参数,mem_address为你要修改的内存块,newsize为你要重新给该内存块分配的大小。接收一个unsigned int形参(需要开辟的空间大小/单位byte字节),返回一个void*(无类型指针)函数原型:void* calloc(unsigned int num,unsigned int size);接收一个两个unsigned int参数,size为需要申请的内存块大小,num为申请多少个连续的内存块。(大部分用于扩大内存块,缩小可能使数据丢失)
2024-08-08 21:13:45
246
原创 常见类型变量和函数指针简单讲解(建议有基础查看)
同上,这里a也是形参为(int int),返回值为int的函数指针的别名。a是形参为(int int),返回值为int的函数指针的别名。a是形参为int,返回值为int的函数地址的指针。int a(int);a是形参为int,返回值为int的函数。a是形参为int,返回值为int*的函数。int* a[3];a是包含3个int*类型元素的数组。
2024-08-08 20:52:07
358
原创 struct结构体的使用及内存分配规则,和union联合体的简单说明
因此,我们在设计结构体时,应该将较小的结构体成员放在一起,这样就能防止内存对齐时浪费太多空间(修改默认对齐数#pragma pack(num),num就为修改的默认对齐数)
2023-11-13 14:55:37
236
原创 内存函数memcpy和memmove的实现
相对strcpy函数,memcpy等内存函数能够通过指针直接操作传入的目标参数,实现对目标的修改,今天就来讲一下其中memcpy和memmove函数的实现首先了解函数功能及函数参数即从源地址source拷贝n个字节到目标地址destin中,因此相比strcpy拷贝字符串遇到'\0'就停止,memcpy内存拷贝有更广的应用函数功能应用:可以看到arr2中的前四个字节内容fedc被拷贝到了arr1中然后定义一个char类型指针ret接收目标地址用于最后返回(
2023-11-10 14:28:59
86
1
原创 浮点数在内存中的存储和取出方式
在这里,先将a=9的二进制序列写出来:00000000...01001,在这里,我们加上小数点后的二进制,小数点后一位为2^-1(2的负1次方),后两位为2^-2,依此类推......*b=9.00的二进制序列则为:00000000...01001.00;S即是二进制的最高位即符号位,以-1^S表示,当S为0时,-1^0为1,S为1时,-1^1为-1,所以S表示浮点数的符号;根据这两个输出我们可以判断浮点数和整形的存储、取出方式肯定都是有区别的,那么,浮点数的存储、取出方式是什么呢。
2023-06-05 09:51:45
698
1
原创 扫雷基础版实现
当排到的不是雷时,就需要显示周围雷的数量,这里我们使用函数GetMines()来计算周围雷的数量,这里我们把非雷和雷初始化‘0’和‘1’的好处就来了,‘0’的ASCLL码值为48,‘1’为49,所以我们只需要把周围8个坐标的值加起来减8乘以‘0’,最后的结果就是数字雷的数量了,返回这个值就行了。然后把这个值赋给玩家输入的坐标,再打印一遍展示给玩家的棋盘,最后当win步数=棋盘总数-雷数时,游戏结束打印“你赢了”printf("--------------扫雷游戏--------------\n");
2023-05-13 15:53:12
91
1
原创 c语言实现三子棋
接下来,我们就需要在main函数实现.c文件里去反复调用功能函数实现程序了,这里使用game()函数来实现,创建一个ret变量来保存我们输赢判断的返回结果,玩家和电脑每次落子都需要判断一下输赢,所以落子→打印棋盘→判断输赢,按照这样的顺序调用函数,如果不符合条件'Z',就跳出循环做判断本局结果。对于玩家的选择我们应该先输入后判断,并且需要循环直到玩家选择退出,这里可以用do-while语句实现,玩家输入后,根据输入值执行不同的结果可以使用switch,那么case 1下面就可以放我们的游戏主体了。
2023-05-09 17:22:08
76
1
原创 认识C语言
C语言是一门面向过程的计算机编程语言,像人类之间交流的语种(英语、中文......),C语言是用来与计算机交流的语言(C/C++/JAVA......);C语言是一门擅长底层开发的语言,电脑(硬件)通过操作系统(windows/Linux/MaxOS...)运行,操作系统通过驱动层驱动硬件工作,应用软件(QQ/微信...)通过操作系统运行,应用软件层以上为上层开发,以下(包括操作系统、驱动层、硬件...)为底层开发;
2023-04-13 20:49:33
91
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人