句柄,haurt,stm32正点原子程序里涉及到的huart等句柄怎样理解

句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。

句柄与普通指针的区别在于,指针包含的是引用对象的内存地址,而句柄则是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。

句柄就是个数字,一般和当前系统下的整数的位数一样,比如32bit系统下就是4个字节。

以上是对句柄是个什么东西的解答。但是发现对我们理解正点原子的程序毫无用处。下边,用一个图来给大家说明一下

如下图,其实,句柄本质就是对底层硬件的指针的使用。句柄是针对内核的。大家可以理解为句柄是一个指向指针的指针。

6660619161a14c4888ab6206f71e6180.jpg

 如图所示。我们把打开手机音乐分成三个层次。第一个是用户层,就是我们手机屏幕上的APP图标;第二个是内核层,就相当于我们的处理器;第三个是硬件层,就是我们手机的音响(声卡)模块。我们分别用酷狗,QQ音乐和网易云音乐同时打开三首不同的歌曲,会发现手机可以同时播放三种不同的音乐。我们把打开APP并且播放音乐这个过程,在程序运行的过程成为进程,由于我们打开的是三个,所以有三个进程。但是我们手机只有一个声卡,三个进程同时要对声卡进行控制,这样就很容易出错误。所以我们在用户层和硬件层之间就加了一个内核层。内核层可以同时接收三个进程发来的信息,然后通过整合,可以把三个信息依次地传给声卡,也就是说,从三个进程到内核,是分三个进程完成的,但是从内核到声卡,只有一个“进程”

理解这个之后,我们再回到句柄,上面我们说句柄是针对内核的,他就相当于,在内核中的一个整理工,把从用户层传过来的进程信息整合到一起,然后对声卡进行控制。因为我们肯定不止有这三个进程,还会有很多,这样,通过句柄这个“整理工”,就可以实现多进程对硬件的访问。

所以在正点原子的程序中,遇到句柄,比如串口通信里的huart,大家可以理解成一个指向指针的指针,处理的时候直接把他当做指针处理,只要是理解他是个什么东西就好了,GPIO InitTypeDef *huart,直接理解为他是一个指向GPIO InitTypeDef结构体的指针,访问该结构体的时候以指针的形式访问,就是用->标识符就可以了

下面简单说一下句柄的由来

句柄(Handle)是一个是用来标识对象或者,项目的标识符,可以用来描述窗体、文件等,值得注意的是句柄不能是常量。HANDLE:句柄,是Windows用来表示对象的(不是C++的对象),HWND是其中一种,HWND是HANDLE,但HANDLE不只是HWND,HANDLE是一个通用句柄表示,HWND是一个专用表示窗口的句柄。

谢谢观看,越努力越幸福,加油哦!点个关注再走呗

 

 

  • 26
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是一个简单的 STM32 串口打印程序,你可以根据自己的需求进行修改: ```c #include "main.h" #include "stdio.h" UART_HandleTypeDef huart2; // 串口句柄 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART2_UART_Init(); while (1) { char str[50]; // 定义一个缓冲区 sprintf(str, "Hello, world!\r\n"); // 往缓冲区中写入内容 HAL_UART_Transmit(&huart2, (uint8_t*)str, strlen(str), 0xFFFF); // 通过串口发送 HAL_Delay(1000); // 延时 1 秒 } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } static void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void) { __disable_irq(); while (1) { } } ``` 在这个程序中,我们使用了 STM32 的 USART2 模块来进行串口通信,使用了 HAL 库提供的函数来进行初始化和发送数据。在主函数中,我们定义了一个缓冲区 `str`,使用 `sprintf` 函数将需要发送的字符串写入缓冲区,最后使用 `HAL_UART_Transmit` 函数将数据通过串口发送出去。 注意:在使用这个程序之前,需要先在 CubeMX 中配置好 USART2 的引脚映射和时钟源。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值