
已关注
关注
重播 分享 赞
Hi3861的API选择有讲究,用错了编译都过不了
GPIO控制看似简单,但有个SDK拼写错误坑了我好久
PWM功能必须用底层API,封装层根本不能用
触摸传感器不支持双边沿中断,只能轮询
ADC实验失败了,但失败也有价值

GPIO初始化
GPIO方向设置(输入还是输出)
GPIO输出控制(高电平还是低电平)
延时函数
```c// 初始化GPIOhi_gpio_init();// 设置GPIO 2为输出模式hi_io_set_func(HI_IO_NAME_GPIO_2, HI_IO_FUNC_GPIO_2_GPIO);hi_gpio_set_dir(HI_GPIO_IDX_2, HI_GPIO_DIR_OUT);// 循环闪烁while(1) {hi_gpio_set_ouput_val(HI_GPIO_IDX_2, HI_GPIO_VALUE1);// 点亮sleep(1);hi_gpio_set_ouput_val(HI_GPIO_IDX_2, HI_GPIO_VALUE0);// 熄灭sleep(1);}```
```LED Blink - PuZhong Hi3861D1=GPIO2[1] D1 ON[1] D1 OFF[2] D1 ON[2] D1 OFF```

按键按下时触发回调函数
实时响应,不占用CPU
需要配置回调函数
定时读取GPIO状态
简单直接
占用CPU,有延迟
下降沿触发(按下)
上升沿触发(松开)
```GPIO 11 ──杜邦线──> KEY1 ──── 板载按键 K1 ──── GNDGPIO 12 ──杜邦线──> KEY2 ──── 板载按键 K2 ──── GND```
```c// 初始化按键(上拉电阻)hi_io_set_pull(KEY1, HI_IO_PULL_UP);hi_io_set_func(KEY1, HI_IO_FUNC_GPIO_11_GPIO);hi_gpio_set_dir(KEY1, HI_GPIO_DIR_IN);// 注册中断回调(下降沿触发)hi_gpio_register_isr_function(KEY1,HI_INT_TYPE_EDGE,HI_GPIO_EDGE_FALL_LEVEL_LOW,& key_callback,NULL);// 回调函数hi_void key_callback(hi_void * arg){printf("[INT] KEY1 pressed!\r\n");}```
```chi_gpio_value key1_val, key1_val_last;hi_gpio_get_input_val(KEY1, &key1_val_last);while (1) {hi_gpio_get_input_val(KEY1, &key1_val);if (key1_val != key1_val_last) {if (key1_val == HI_GPIO_VALUE0) {printf("KEY1 pressed!\r\n");} else {printf("KEY1 released!\r\n");}key1_val_last = key1_val;}usleep(50000); // 50ms轮询}```
```========================================Key Detection - PuZhong Hi3861KEY1=GPIO11, KEY2=GPIO12========================================[INT] KEY1 pressed![POLL] KEY1: PRESSED[POLL] KEY1: RELEASED[INT] KEY2 pressed![POLL] KEY2: PRESSED[POLL] KEY2: RELEASED```
内部有振荡电路
通电就响
只能发单一频率
内部无振荡电路
需要外部提供方波信号
可以发不同频率的声音
```GPIO 14 ──杜邦线──> BP ──── 蜂鸣器```
```c// 初始化蜂鸣器控制引脚hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_GPIO);hi_gpio_set_dir(HI_GPIO_IDX_14, HI_GPIO_DIR_OUT);// 发出声音(方波信号)for (int i = 0; i < 1000; i++) {hi_gpio_set_ouput_val(HI_GPIO_IDX_14, HI_GPIO_VALUE1);usleep(500); // 高电平500微秒hi_gpio_set_ouput_val(HI_GPIO_IDX_14, HI_GPIO_VALUE0);usleep(500); // 低电平500微秒}```
高电平:500微秒
低电平:500微秒
周期:1000微秒 = 1毫秒
频率:1 / 0.001 = 1000Hz

```cIoTPwmInit(HI_PWM_PORT_PWM2);IoTPwmStart(HI_PWM_PORT_PWM2, 50, 40000); // 占空比50%```
```chi_pwm_init(HI_PWM_PORT_PWM2);hi_pwm_start(HI_PWM_PORT_PWM2, 20000, 40000); // 占空比50%```
```c// 1. 设置GPIO 2为PWM2输出hi_io_set_func(HI_IO_NAME_GPIO_2, HI_IO_FUNC_GPIO_2_PWM2_OUT);// 2. 初始化PWMhi_pwm_init(HI_PWM_PORT_PWM2);// 3. 呼吸灯效果while (1) {// 渐亮for (int duty = 0; duty <= 40000; duty += 400) {hi_pwm_start(HI_PWM_PORT_PWM2, duty, 40000);usleep(10000); // 10ms}// 渐暗for (int duty = 40000; duty >= 0; duty -= 400) {hi_pwm_start(HI_PWM_PORT_PWM2, duty, 40000);usleep(10000); // 10ms}}```
触摸时,人体电容改变传感器电容值
```触摸传感器模块 开发板P1排针────────────────────────────────────VCC (电源正) → 3V3(右排)GND (地) → GND(左排)DO (数字输出) → GPIO 11(左排第6个)AO (模拟输出) → 不接```
```chi_gpio_register_isr_function(TOUCH_SENSOR,HI_INT_TYPE_EDGE,HI_GPIO_EDGE_BOTH, // 双边沿触发&touch_callback,NULL);```
```chi_gpio_value val, val_last;hi_gpio_get_input_val(TOUCH_SENSOR, &val_last);while (1) {hi_gpio_get_input_val(TOUCH_SENSOR, &val);if (val != val_last) {if (val == HI_GPIO_VALUE1) {// 触摸检测到hi_gpio_set_ouput_val(LED_D1, HI_GPIO_VALUE1);printf("Touch detected! LED ON\r\n");} else {// 触摸释放hi_gpio_set_ouput_val(LED_D1, HI_GPIO_VALUE0);printf("Touch released! LED OFF\r\n");}val_last = val;}usleep(50000); // 50ms轮询}```
```chi_io_set_pull(TOUCH_SENSOR, HI_IO_PULL_DOWN);```
```========================================Touch Sensor Test - PuZhong Hi3861Sensor DO -> GPIO 11LED D1 -> GPIO 2========================================[INIT] Touch sensor initial state: RELEASED[POLL] Touch detected! LED ON[POLL] Touch released! LED OFF[POLL] Touch detected! LED ON[POLL] Touch released! LED OFF```
```c#include"hi_adc.h"hi_u16 adc_value;float voltage;// 读取ADC值hi_adc_read(HI_ADC_CHANNEL_5, &adc_value,HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_AUTO, 0);// 转换为电压值voltage = hi_adc_convert_to_voltage(adc_value);printf("ADC Value: %d, Voltage: %.2fV\r\n", adc_value, voltage);```

`hi_adc_read()`的参数含义不清楚:-`HI_ADC_EQU_MODEL_4`是什么意思?-`HI_ADC_CUR_BAIS_AUTO`是什么意思?-`delay_cnt`应该设为多少?
用万用表测量电位器引脚,确认连接
| 场景 | 推荐选择 | 原因 ||------|---------|------|| GPIO控制 | `hi_gpio_*` | 底层API更可靠 || PWM控制 | `hi_pwm_*` | 封装层不可用 || GPIO复用 | `hi_io_set_func()` | Hi3861专用API |
文档不完善,容易踩坑
直接操作硬件,行为可预测
文档相对完善
社区经验丰富
| 错误写法 | 正确写法 | 说明 ||---------|---------|------|| `hi_gpio_set_output_val` | `hi_gpio_set_ouput_val` | SDK拼写错误(`ouput`不是`output`) || `IoSetFunc` | `hi_io_set_func` | Hi3861使用`hi_io_*`系列 || `IOT_IO_NAME_GPIO_*` | `HI_IO_NAME_GPIO_*` | 使用`HI_IO_NAME_*`系列 || `HI_GPIO_EDGE_BOTH` | 不存在 | 不支持双边沿触发,改用轮询 || `IoTPwm*` | `hi_pwm_*` | PWM封装层不可用,使用底层API |

```c// 1. 初始化hi_gpio_init();// 2. 设置功能hi_io_set_func(GPIO, HI_IO_FUNC_GPIO_X_GPIO);// 3. 设置方向hi_gpio_set_dir(GPIO, HI_GPIO_DIR_OUT);// 4. 控制输出hi_gpio_set_ouput_val(GPIO, HI_GPIO_VALUE1); // 高电平hi_gpio_set_ouput_val(GPIO, HI_GPIO_VALUE0); // 低电平```
```c// 1. 初始化hi_gpio_init();// 2. 设置功能hi_io_set_func(GPIO, HI_IO_FUNC_GPIO_X_GPIO);// 3. 设置上下拉hi_io_set_pull(GPIO, HI_IO_PULL_UP); // 上拉(默认高电平)// 或hi_io_set_pull(GPIO, HI_IO_PULL_DOWN); // 下拉(默认低电平)// 4. 设置方向hi_gpio_set_dir(GPIO, HI_GPIO_DIR_IN);// 5. 读取输入hi_gpio_value val;hi_gpio_get_input_val(GPIO, &val);```
✅ 支持上升沿触发
✅ 支持下降沿触发
✅ 支持高电平触发
✅ 支持低电平触发
❌ 不支持双边沿触发
示例:```c// 50%占空比hi_pwm_start(HI_PWM_PORT_PWM2, 20000, 40000);// 25%占空比hi_pwm_start(HI_PWM_PORT_PWM2, 10000, 40000);// 100%占空比hi_pwm_start(HI_PWM_PORT_PWM2, 40000, 40000);```
LED快闪——嵌入式界的"Hello World"
ADC电位器采集——失败的实验
API选择原则
常见错误速查
GPIO工作流程
中断 vs 轮询
PWM参数设置
开发流程建议
调试技巧
要理解电路原理
要知道引脚连接
要会用测试工具
要理解API用法
要注意参数范围
要处理异常情况
要看官方文档
要参考社区经验
要记录自己的经验
帮我分析编译错误,快速定位问题
帮我查阅API文档,避免踩坑
帮我优化代码实现,提高效率
帮我记录实验经验,建立知识库
自动维护API验证文档
记录每次实验的成功和失败
总结常见错误和解决方案
建立项目知识库,方便查阅
以前查文档要半天,现在DuMate直接给出答案
以前调试要试错多次,现在DuMate帮我分析原因
以前记录要手动整理,现在DuMate自动生成文档
保持好奇心
保持耐心
保持记录
保持分享
有个好搭档(比如DuMate)
夜雨聆风