电子说
周立功教授新书《面向AMetal框架与接口的编程(上)》,对AMetal框架进行了详细介绍,通过阅读这本书,你可以学到高度复用的软件设计原则和面向接口编程的开发思想,聚焦自己的“核心域”,改变自己的编程思维,实现企业和个人的共同进步。
第七章为面向通用接口的编程,本文内容为7.4 温度采集接口、7.5 键盘。
7.4 温度采集接口
>>> 7.4.1 温度传感器通用接口
AMetal 提供了温度采集的通用接口,仅包含一个温度读取接口,用于读取当前的温度值,其函数原型为(am_temp.h):
其中,handle 为温度传感器的句柄,其可以通过初始化具体的温度传感器(如LM75)获得,p_temp 为输出参数,用于返回当前的温度值,为了避免小数运算,这里使用有符号的32 位整数表示温度值(单位:摄氏度),且其值为实际温度值的1000 倍,表示温度值的分辨率为0.001℃。读取温度的范例程序详见程序清单7.25。
程序清单7.25 am_temp_read()范例程序
显然要使应用程序可以使用通用接口读取温度,就必须获取温度传感器的handle,这就需要为具体的温度传感器提供相应的驱动。
>>> 7.4.2 LM75B 驱动
LM75B 是NXP 半导体推出的具有I2C 接口的数字温度传感器芯片,AMetal 已经提供了其对应的驱动,仅包含一个初始化函数,其函数原型(am_temp_lm75.h)为:
该函数意在获取LM75 温度传感器的实例句柄,进而使用通用接口读取温度。其中:
p_lm75 为指向am_temp_lm75_t 类型实例的指针;
p_devinfo 为指向am_temp_lm75_info_t 类型实例信息的指针。
1. 实例
定义am_temp_lm75_t 类型(am_temp_lm75.h)实例如下:
其中,g_temp_lm75 为用户自定义的实例,其地址作为p_lm75 的实参传递。
2. 实例信息
实例信息主要描述了与LM75 相关的信息,即LM75 的I2C 从机地址等,其类型am_temp_lm75_info_t 的定义(am_temp_lm75.h)如下:
其中,i2c_addr 指定了LM75 的7-bit 从机地址(在很多应用中,常常使用8 位数据表示从机地址, 8 位地址的最低位为读写方向位,由于在AMetal 中,读写方向位无需用户控制,驱动会自动实现对读写方向位的控制,因此在AMetal 中需要由用户提供的7-bit 从机地址不包含读写方向位),LM75 的7-bit 从机地址为1001A2A1A0,最低三位由A0~A2 引脚电平决定,在AM824-Core 中,板载了一个LM75 温度传感器。由此可见,A0~A2 均与地连接,为低电平,因此,板载LM75 的地址为1001000,即:0x48。其实例信息定义如下:
其中,g_temp_lm75_info 为用户自定义的实例信息,其地址作为p_info 的实参传递。
3. I2C 句柄i2c_handle
以I2C1 为例,其实例初始化函数am_lpc82x_i2c1_inst_init()的返回值即可作为实参传递给i2c_handle。即:
4. 实例句柄
基于实例、实例信息和I2C 句柄,即可完成LM75 的初始化。比如:
初始化函数的返回值即为温度传感器的句柄,若返回值为NULL,说明初始化失败;若返回值不为NULL,说明返回了有效的handle,其可以作为温度读取接口的参数。为了便于配置LM75(如修改7-bit 从机地址等)。基于模块化编程思想,将初始化相关的实例、实例信息等的定义存放到LM75 的配置文件中,通过头文件引出实例初始化函数接口,源文件和头文件的程序范例分别详见程序清单7.26 和程序清单7.27。
程序清单7.26 LM75 实例初始化函数实现(am_hwconf_lm75.c)
程序清单7.27 LM75 实例初始化函数声明(am_hwconf_lm75.h)
后续只需要使用无参数的实例初始化函数即可完成LM75 实例的初始化,获取温度传感器句柄,即执行如下语句:
当完成初始化后,即可使用通用的温度读取接口获取当前温度值,读取并通过串口打印当前温度值的范例程序详见程序清单7.28。
程序清单7.28 使用LM75 检测当前温度的范例程序
7.5 键盘
>>> 7.5.1 通用键盘接口
由于此前的按键处理方式与具体的MCU、键盘的组织形式(独立按键或矩阵键盘等)完全耦合在一起,为此AMetal 提供了一种通用键盘接口。其函数原型为:
其中,p_handler 为指向按键事件处理器的指针,pfn_cb 为指向用户自定义按键处理函数的指针,p_arg 为按键处理函数的用户参数。
1. p_handler
am_input_key_handler_t 是按键事件处理器的类型,它是在am_input.h 文件中使用typedef自定义的一个类型。即:
基于此,在使用按键时,首先需要定义一个该类型的按键事件处理器实例(对象),其本质是定义一个结构体变量。比如:
即可该实例的地址&key_handler 作为参数传递给函数的形参p_handler。
2. pfn_cb
am_input_cb_key_t 是按键处理函数的指针类型,它是在am_input.h 文件中使用typedef自定义的一个类型。即:
当有按键事件发生时(按键按下或按键释放),均会调用pfn_cb 指向的按键处理函数,完成相应的按键处理功能。当该函数被调用时,传递给p_arg 的值为用户参数,传递给key_code 的值为按键的编码,它是在am_input_code.h 文件中使用宏进行定义的,比如,KEY_1、KEY_2 等,传递给key_state 的值为按键的状态,详见表7.5。
表7.5 按键状态
以AM824-Core 开发板为例,KEY 对应的按键编码为KEY_KP0。当KEY 键按下时,则LED0 点亮;当KEY 键释放后,则LED0 熄灭,相应的按键处理函数详见程序清单7.29。
程序清单7.29 按键处理函数范例程序
函数名即可作为参数传递给am_input_key_handler_register()函数的形参pfn_cb。
3. p_arg
通常调用am_input_key_handler_register()函数传递给形参p_arg 的值会在调用事件处理回调函数时,传递给事件处理函数的p_arg 形参。
如果不使用,则在调用am_input_key_handler_register()函数时,将p_arg 的值设置为NULL,注册按键处理器的范例程序详见程序清单7.30。
程序清单7.30 按键处理函数范例程序
注册按键处理器后,当有键按下或按键释放时,均会调用注册按键处理器时指定的回调函数,即程序清单7.29 中的__input_key_proc ()函数。为了分离各个键的处理代码,可以注册多个按键事件处理器,每个处理器负责处理一个或多个键,详见程序清单7.31。
程序清单7.31 注册多个按键处理器范例程序
通用键盘接口的特点是屏蔽了底层的差异性,使应用程序与底层MCU、键盘的具体形式无关,可以轻松地实现应用程序的跨平台。
在实际的应用中,键盘的表现形式是多种多样的,比如,直接使用GPIO 驱动的独立键盘(一个或多个独立按键组成的键盘)和矩阵键盘和标准的PS/2 接口键盘,以及使用ZLG推出的I2C 接口的ZLG72128 键盘与数码管驱动芯片制作的键盘等。虽然各种按键的检测方法都不相同,但只要提供相应的驱动,即可将接口统一起来。如同在PC 上使用外部设备时,需要安装对应的驱动一样。AMetal 提供了常用键盘的驱动,用户直接使用无需关心按键检测的方法或按键消抖等细节问题。
>>> 7.5.2 独立键盘驱动
AMetal 独立键盘的驱动提供了一个初始化函数,使用该函数初始化一个独立键盘实例后,即可使用通用接口使用按键。其函数原型为:
其中,p_dev 为指向am_key_gpio_t 类型实例的指针,p_info 为指向am_key_gpio_info_t类型实例信息的指针。
1. 实例
定义am_key_gpio_t 类型(am_key_gpio.h)实例如下:
其中,g_key_gpio 为用户自定义的实例,其地址作为p_dev 的实参传递。
2. 实例信息
实例信息主要描述与独立键盘相关的信息,比如,使用的GPIO 引脚号,独立按键的个数,以及对应的按键编码等信息。其类型am_key_gpio_info_t 的定义(am_key_gpio.h)如下:
其中,p_pins 指向存放各独立按键对应引脚号的数组,如在AM824-Core 开发板上,有一个多功能按键可以当做独立按键使用。当J14 的1 和2 短接时,KEY 与PIO_KEY(PIO0_1)连接,此时,按键KEY 当做独立按键使用。基于此,可以定义一个存放引脚号的数组:
该数组的地址即可作为p_pins 的值。由于AM824 开发板只有一个独立按键,因此数组仅有一个元素,其值为与该独立按键连接的引脚号,即PIO0_1。当存在多个独立按键时,继续在该数组后添加数据元素即可。同时,由于引脚号在系统启动后不会修改,因此使用了const 修饰符。
为了区分各个按键,要求每个按键都具有一个唯一的编码值,因此需要为独立键盘中的各个按键指定一个编码,p_codes 即指向存放各独立按键对应编码的数组,其编码与p_pins指向的数组中各个独立按键一一对应。比如,设置AM824ZB 开发板中的独立按键对应编码为KEY_KP0,则可以定义如下数组:
该数组的地址即可作为p_codes 的值。在通用按键处理接口的程序范例中,使用了按键编码KEY_F1 作为独立按键的编码,按键编码KEY_F1 就是在这里配置的,如果需要使用其它按键编码,直接修改即可。按键编码可以是任意整数值,但建议使用类似KEY_KP0 这样的标准按键编码,其是在am_input_code.h 文件中定义的宏。
pin_num 指定了独立键盘中独立按键的个数,其应该与p_pins 和p_codes 指向的数组大小保持一致,在AM824-Core 开发板上只有一个独立按键,因此该值为1。
对于独立按键来讲,不同的电路可能影响按键按下时的电平,为了让驱动准确获取这一信息,使用active_low 成员表明按键按下时的电平,若按键按下时为低电平,则该值为AM_TRUE,反之该值为AM_FALSE。查看相应的原理图可知,当按键按下时,GPIO 引脚为低电平,因此active_low 的值应该设置为AM_TRUE。
scan_interval_ms 指定了按键扫描的时间间隔,即每隔该段时间执行一次按键检测,检测是否有按键事件发生(按键按下或按键释放),通常将该值设置为10 ms。基于以上信息,实例信息定义如下:
基于实例和实例信息,即可完成独立键盘的初始化。比如:
初始化完成后,即可使用通用键盘处理接口处理编码为KEY_KP0 的按键。为了便于配置独立键盘(修改实例信息)。基于模块化编程思想,将初始化相关的实例和实例信息等的定义存放到独立键盘的配置文件中,通过头文件引出实例初始化函数接口,源文件和头文件的程序范例分别详见程序清单7.32 和程序清单7.33。
程序清单7.32 独立键盘实例初始化函数实现(am_hwconf_key_gpio.c)
程序清单7.33 独立键盘实例初始化函数声明(am_hwconf_key_gpio.h)
后续只需要使用无参数的实例初始化函数,即可完成独立键盘实例的初始化:
初始化完成后,即可使用通用键盘处理接口处理编码为KEY_KP0 的按键。
在AM824ZB 中,独立键盘作为一种板载资源,在系统启动时已经默认进行了独立键盘的初始化操作,因此在程序清单7.30 所示的范例程序中,没有调用独立键盘实例初始化函数就可以使用板载的独立按键。
若用户不需要使用独立按键,为了节省内存空间,可以将am_prj_config.h 工程配置文件中的AM_CFG_KEY_GPIO_ENABLE 宏值修改为0,裁剪掉独立键盘,该宏本质上控制了板级初始化函数中的一段程序,详见程序清单7.34。
程序清单7.34 在板级初始化中裁剪独立键盘的原理
注:板级初始化函数在系统启动时自动调用,初始化完毕后才会进入应用程序入口,即am_main()。
>>> 7.5.3 矩阵键盘驱动
类似地,AMetal 矩阵按键的驱动也提供了一个初始化函数,使用该函数初始化一个矩阵键盘实例后,即可使用通用接口使用按键。其函数原型为:
其中的p_dev 为指向am_key_matrix_gpio_softimer_t 类型实例的指针,p_info 为指向am_key_matrix_gpio_softimer_info_t 类型实例信息的指针。
1. 实例
定义am_key_matrix_gpio_softimer_t 类型(am_key_matrix_gpio.h)实例如下:
其中,miniport_key 为用户自定义的实例,其地址作为p_dev 的实参传递。
2. 实例信息
实例信息描述了与矩阵键盘相关的信息,其类型am_key_matrix_gpio_softimer_info_t 的定义(am_key_matrix_gpio.h)如下:
其中, key_matrix_gpio_info 成员包含了GPIO 驱动型矩阵键盘的相关信息;scan_interval_ms 指定了按键扫描的时间间隔(单位:毫秒),即每隔该段时间执行一次按键检测,检测是否有按键事件发生(按键按下或按键释放),该值一般设置为5 ms 即可。
key_matrix_gpio_info 类型am_key_matrix_gpio_info_t 定义(am_key_matrix_gpio.h)为:
其中,base_info 成员包含了矩阵键盘的基础信息,如矩阵键盘的行数和列数、各按键对应的编码等。p_pins_row 指向存放矩阵键盘行线对应引脚号的数组,p_pins_col 指向存放矩阵键盘列线对应引脚号的数组。
若使用MiniPort-Key 与AM824-Core 相连接时,KR0、KR1 为行线,分别与PIO0_6 和PIO0_7 连接,KL0、KL1 为列线,分别与PIO0_17 和PIO0_23 连接。定义行线引脚数组和列线引脚数组为:
两个数组的地址可分别作为p_pins_row 和p_pins_col 的值。
base_info 成员的类型am_key_matrix_base_info_t 定义(am_key_matrix_base.h)如下:
其中,row 和col 分别表示矩阵键盘的行数目和列数目,若使用MiniPort-Key 矩阵键盘,其为2×2 的矩阵键盘,因此行数目和列数目均为2。
p_codes 指向存放矩阵键盘中各按键对应编码的数组,为了与硬件标号一致,分配给各个按键的编码依次为:KEY_0、KEY_1、KEY_2、KEY_3。则可以定义如下数组:
该数组的地址即可作为p_codes的值。active_low 表明按键按下是否为低电平,由电路的设计可知,行线外接了上拉电阻,配置为输入模式时默认会是高电平。因此,应该使用低电平驱动方式,列线输出低电平,当按键按下时,就会检测到低电平, 即该值应为AM_TRUE。scan_mode 表示扫描方式,支持的方式有行扫描和列扫描方式,它们对应的宏名详见表7.6。如使用列扫描,则该值为AM_KEY_MATRIX_SCAN_MODE_COL。基于以
上信息,完整的实例信息可以定义如下:
表7.6 矩阵键盘扫描方式
基于实例和实例信息,即可完成MiniPort-Key 矩阵键盘的初始化。比如:
初始化完成后,即可使用通用键盘处理接口处理编码为KEY_0~KEY_3 的按键。为了便于配置矩阵键盘(修改实例信息)。基于模块化编程思想,将初始化相关的实例、实例信息等的定义存放到独立键盘的配置文件中,通过头文件引出实例初始化函数接口,源文件和头文件的程序范例分别详见程序清单7.35 和程序清单7.36。
程序清单7.35 矩阵键盘实例初始化函数实现(am_hwconf_miniport _key.c)
程序清单7.36 矩阵键盘实例初始化函数声明(am_hwconf_miniport_key.h)
后续只需要使用无参数的实例初始化函数,即可完成矩阵键盘实例的初始化:
当完成初始化后,即可使用通用键盘处理接口处理编码为KEY_0~KEY_3 的按键。在AM824-Core 中,矩阵键盘作为可选的配板资源,在系统启动时没有像独立键盘那样默认就执行了初始化操作,因此如需使用矩阵键盘,则必须手动调用矩阵键盘实例初始化函数。
基于按键通用接口编写一个简易的应用程序:当有键按下时,蜂鸣器在发出“嘀”的一声的同时,通过LED0 和LED1 的组合显示按键编号。比如,当KEY0 键按下时,两个LED灯均熄灭。当KEY1 按下时,则显示01,即LED0 亮,LED1 熄灭,依此类推。将应用程序存放在app_key_code_led_show.c 文件中,其接口声明在app_key_code_led_show.h 文件中,详见程序清单7.37 和程序清单7.38。
程序清单7.37 矩阵键盘应用程序实现(app_key_code_led_show.c)
程序清单7.38 矩阵键盘应用程序接口声明(app_key_code_led_show.h)
使用MiniPort-Key 的4 个按键展示此应用程序的功能的主程序详见程序清单7.39。
程序清单7.39 矩阵键盘应用程序主程序
全部0条评论
快来发表一下你的评论吧 !