GPIO
1.1概述
本案例将使用板载的红色LED来验证GPIO的输出功能,将演示如何在开发板上使用GPIO输出功能去点亮红色LED灯。
1.2查看LED灯对应的GPIO引脚
在开发板上红色LED的连接电路图如下图所示,红色LED的控制引脚与主控芯片的GPIO_12连接,所以需要编写软件去控制GPIO_12输出高低电平实现LED灯的亮灭。
1.3 GPIO API分析
本案例主要使用了以下几个API完成GPIO输出功能:
GPIO接口函数主要在iot_gpio.h头文件中:
IoTGpioInit:初始化GPIO外设。
GpioSetDir:设置GPIO输出方向。
IO接口函数主要在hal_iot_gpio.c头文件中:
IoTGpioSetOutputVal:设置GPIO输出电平。
1.4 主要代码分析
LedTask()为LED灯测试主任务,该任务先调用 IoTGpioInit()初始化GPIO,因为LED灯的控制引脚接在GPIO_12上,所以通过IoTGpioSetDir()将GPIO_12设置为普通GPIO的输出模式。最后在死循环里面间隔 1s 输出GPIO_12的高低电平,实现LED灯闪烁的现象。
1.5运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,开发板的红色LED灯开始闪烁间隔为1秒。
1.6代码
中断
2.1概述
本示例将演示如何在开发板上使用GPIO输入功能去控制LED亮灭。
2.2查看硬件
a) 在开发板上LED的连接电路图如下图所示,LED的控制引脚与主控芯片的GPIO_7连接,所以需要编写软件去控制GPIO_7输出高低电平实现LED灯的亮灭。
b) 从原理图中可以看出,按键F1的检测引脚与主控芯片的GPIO_11连接,所以需要编写软件去读取GPIO_11判断按键是否被按下。
2.3 API分析
hi_io_set_pull (unsigned int id, IotGpioPull val);
设置GPIO的上下拉方式。
id表示GPIO引脚号。
val表示要设置的上拉或下拉。
unsigned int hi_io_set_func(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity, GpioIsrCallbackFunc func, char *arg);
启用GPIO引脚的中断功能。这个函数可以用来为GPIO pin设置中断类型、中断极性和中断回调。
id 表示GPIO引脚号。
intType表示中断类型。
intPolarity表示中断极性。
func表示中断回调函数。
arg表示中断回调函数中使用的参数的指针。
2.4 主要代码分析
这部分代码主要分析按键触发中断的功能代码,这里以按键F1为例,按键F1的检测引脚与主控芯片的GPIO_11连接,首先通过调用IoTGpioSetFunc()和IoTGpioSetDir()将GPIO_11设置为普通GPIO的输入模式。从前面原理图可知,当按键按下时,GPIO_11会被下拉到地,所以这里要使用IoTGpioSetPull()将GPIO_11引脚设置为上拉,这样才能产生电平的跳变。最后通过IoTGpioRegisterIsrFunc()将中断类型设置为边沿触发,且为上升沿触发,当按键被按下时并释放时,GPIO_11会从低电平转为高电平,产生一个上升沿,这个时候就会触发中断并回调F1_Pressed函数。在F1_Pressed函数中实现翻转LED灯操作。
2.5 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,开发板开始正常工作,按下并释放F1按键LED会点亮,再按下并释放F1按键LED会熄灭。
2.6代码
PWM输出
3.1概述
本示例将演示如何在开发板上使用GPIO的PWM功能实现呼吸灯的效果。
3.2查看硬件
在开发板上LED的连接电路图如下图所示,LED的控制引脚与主控芯片的GPIO_8连接,所以需要编写软件去控制GPIO_8输出高低电平实现LED灯的亮灭。
3.3 API分析
unsigned int IoTPwmInit(unsigned int port);
初始化PWM功能。
port表示PWM设备端口号。
unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq);
根据输入参数输出PWM信号。
portPWM端口号。
duty占空比。
freq分频倍数。
3.4 主要代码分析
PWMTask()为PWM测试主任务,该任务先调用 IoTGpioInit()初始化GPIO,因为LED灯的控制引脚接在GPIO_8上,所以通过调用IoTGpioSetFunc()将GPIO_8复用为PWM功能,并通过IoTPwmInit()初始化PWM2端口,最后在死循环里面间隔10us输出不同占空比的PWM波,实现呼吸灯的效果
3.5 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,开发板开始正常工作,LED开始不断变化亮度,实现呼吸灯的效果。
3.6 代码
ADC采样
4.1概述
本示例将演示如何在开发板上通过按下按键改变GPIO口的电压,并使用ADC读取GPIO的电压值。
4.2查看硬件
a) 从原理图中可以看出,按键F1的检测引脚与主控芯片的GPIO_11连接。
b) 从Hi3861V100的数据手册可以看出GPIO_11连接的是ADC通道5,所以需要读取ADC通道5的值。
4.3 API分析
unsigned int hi_adc_read (unsigned int channel, unsigned short *data, IotAdcEquModelSel equModel, IotAdcCurBais curBais, unsigned short rstCnt);
根据输入参数从指定的ADC通道读取一段采样数据。
channel表示ADC通道。
data表示指向存储读取数据的地址的指针。
equModel 表示平均算法的次数。
curBais 表示模拟功率控制模式。
rstCnt 指示从重置到转换开始的时间计数。一次计数等于334纳秒。值的范围必须从0到0xFF。
4.4 主要代码分析
该函数通过使用AdcRead()函数来读取 ADC_CHANNEL_5
的数值存储在data中, IOT_ADC_EQU_MODEL_8
表示8次平均算法模式,IOT_ADC_CUR_BAIS_DEFAULT
表示默认的自动识别模式,最后通过 data * 1.8 * 4 / 4096.0
计算出实际的电压值。
4.5 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,当F1按键未按下时采集到的电压为3.3V左右,当按键按下时,电压变为0.2V左右。
4.6代码
I2C总线驱动NFC
5.1概述
本示例将演示如何在开发板上使用I2C协议向NFC芯片写入指令,使NFC芯片在不供电的情况下接收到NFC信号就能点亮NFC灯。
5.2查看硬件
a) 在开发板上NFC的连接电路图如下图所示,NFC_SDA与主控芯片的GPIO_00连接,NFC_SCL与主控芯片的GPIO_01连接。
b) 从Hi3861V100的数据手册可以看出GPIO_00和GPIO_01连接的是I2C1。
5.3 API分析
本示例主要使用了以下API完成I2C采样的功能
unsigned int IoTI2cInit(unsigned int id, unsigned int baudrate);
用指定的频率初始化I2C设备。
Id I2C设备ID。
Baudrate I2C频率。
unsigned int IoTI2cSetBaudrate(unsigned int id, unsigned int baudrate);
为I2C设备设置频率。
id I2C设备ID。
baudrate I2C频率。
hi_u32 hi_i2c_write(hi_i2c_idx id, hi_u16 device_addr, const hi_i2c_data *i2c_data)
将数据写入I2C设备。
id I2C设备ID。
device_addr I2C设备地址。
i2c_data 表示写入的数据。
5.4 主要代码分析
程序主要是通过I2C将{0x10,0x3D,0x01,0x00,0X00,0X00}这6个字节发送给从机地址为0XA8的NFC芯片,NFC接收到以上6个字节的指令则会开启能量回收功能,从而在不接电源的情况下,通过从手机发射的NFC信号收集能量来点亮LED,写入其他指令则LED不亮。
5.5 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,看到串口打印出I2C WRITE DATA SUCCESS拔下开发板的下载线,打开手机NFC功能,接近开发板的NFC线圈则会看到NFC灯被点亮。
5.6代码
步进电机
6.1概述
本示例将演示如何在开发板上使用4路GPIO输出脉冲,去控制步进电机旋转。
6.2硬件连接
GPIO14—A相 GPIO13—B相 GPIO2—C相 GPIO7—D相
6.3 API分析
6.3.1接口motor_init
<1 >功能描述
初始化电机驱动信号输出管脚,声明结构体并初始化参数,然后返回该结构体指针。
<2 >接口原型
motor_param * motor_init(unsigned char * gpio,unsigned char phases,unsigned char stepalg); < 3>参数格式
- 控制信号管脚 unsigned char * gpio 用户只需传入gpio数组首地址
- 电机相数unsigned char phases 用户需要传入电机的相数
- 电机驱动算法unsigned char stepalg one:表示一相一拍 two表示一相两拍
- 返回值 电机结构体指针motor_param *
typedef struct{
unsigned char * gpio; //电机GPIO
unsigned char phases; //当前电机相数
volatile int speed; //电机转速
unsigned char step; //电机步进计数
enum {one,two} stepalg; //电机驱动算法,0:一相一拍1:一相两排
osThreadId_t taskID; //电机驱动任务ID
} motor_param;
6.3.2接口 motor_setspeed
<1 >功能描述
设置电机转速。
<2 >接口原型
void motor_setspeed(int speed,motor_param * motorparam);
< 3>参数格式
(1)电机转速 int speed, 大于0:顺时针旋转,小于0:逆时针旋转,等于0:停止旋转。
(2)电机结构体
typedef struct{
unsigned char * gpio; //电机GPIO
unsigned char phases; //当前电机相数
volatile int speed; //电机转速
unsigned char step; //电机步进计数
enum {one,two} stepalg; //电机驱动算法,0:一相一拍1:一相两排
osThreadId_t taskID; //电机驱动任务ID
} motor_param;
6.4 主要代码分析
static void motor_main(void)
{
motor_dev * dev;
unsigned char gpio[]={14,13,2,7};//gpio 14 13 2 7
dev = motor_init(gpio,4,two);
for(;;)
{
motor_setspeed(-50,dev);
printf("motor set success1!\n");
usleep(10000000);
motor_setspeed(50,dev);
printf("motor set success2!\n");
usleep(10000000);
}
}
定义gpio数组存放所用管脚编号按照ABCD相的顺序排列,初始化电机为GPIO14、13、2、7四个管脚4相8拍算法驱动。进入死循环,开始设置电机以50的转速逆时针旋转,然后延时10秒,再以50的转速顺时针旋转,再延时10秒。从而控制电机正反转。
6.5 运行结果
示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,电机将正转10秒,然后再反转10秒,如此一直循环。