全部文档
OneOS简介 硬件支持 快速开发指南 编译构造工具 API参考文档 高级语言 用户编程手册 OnePos定位 应用笔记 FAQ

开发板及操作系统简介

万耦开发板

万耦开发板,是中国移动推出的基于STM32,NXP等芯片的一个系列开发板,其由不同处理核心的核心板与万耦底板组成。一般来说万耦底板是通用的,核心板当前有STM32L475VGT6、STM32F401VET6与NXPLPC55S69三个型号,用户可根据需求选择不同的核心板。

oneos_board

以STM32L475VGT6为核心的万耦开发板为例,资源如下:

资源类别 资源说明
MCU STM32L475VGT6,主频 80MHz,1024KB FLASH ,128KB SRAM;
存储 外部 FLASH W25Q64(SPI,64Mbit);
人机交互 5个按键(1个RESET按键),RGB灯,电源指示LED灯,呼吸灯,串口指示灯,
4G模组指示灯,WIFI指示灯,4G电源指示灯,1.3寸LCD显示器,1个蜂鸣器;
板载模块 AHT10温/湿度传感器,AP3216C光强/接近位置传感器,IRM-56384红外接收传感器,IR12-21C/TR8红外发送传感器,
ICM-20602六轴传感器,WIFI模组,ES8388音频解码芯片,GMI4015P-2C麦克风模块,SN65HVD230DR CAN通信模块,
ST7789VW LCD显示器,LP5907MFX-3.3/NOPB稳压器(4G,WIFI,SENSOR,AUDIO可控供电);
关键接口 USB接口:可用于连接USB设备;20 Pin JTAG接口:可用于代码调试下载;
Mini PCI-E接口:可用于连接4G模组;USB转UART接口,可用于串口通信;
CAN通信接口;TF卡接口;耳机接口;

注意,表中MCU与存储资源位于核心板上,其他资源均位于万耦开发板底板上。

OneOS物联网操作系统

OneOS 是中国移动针对物联网领域推出的轻量级操作系统,具有可裁剪、跨平台、低功耗、高安全等特点,支持ARM Cortex-M、MIPS、RISC-V等主流芯片架构,兼容POSIX、CMSIS等标准接口,支持MicroPython语言开发,提供图形化开发工具,能够有效提升开发效率并降低开发成本,帮助用户开发稳定可靠、安全易用的物联网应用。您可以通过中国移动物联网操作系统官网了解更多关于物联网操作系统的信息。

进入到OneOS操作系统代码根目录下,我们可以看到有多个文件夹和文件,如下图:

OneOS

各个目录或文件的作用描述见下表。

目录或文件名称 描述
arch 存放和 MCU(或 CPU )架构体系相关的代码
common 存放一些通用的没有具体业务指向的程序代码,所有模块都可以使用,不通过编译选项控制是否编译,采用默认编译进工程的方式
components 存放组件代码,可进行裁剪
demos 存放内核或组件的对外接口如何使用的示实验序
docs 存放一些文档,如编码规范、编程指南等
drivers 存放驱动的抽象层代码和具体外设的驱动代码
kernel 存放内核代码,如任务管理及调度、任务间同步以及通信、内存管理等代码
libc Libc 库部分硬件相关接口的底层适配。
osal OneOS操作系统接口抽象层,支持Posix接口、CMSIS接口、RT-Thread接口等
projects 各种开发板的示例工程
scripts 存放OneOS-Cube工具在编译构造时所需要的脚本文件
thirdparty 存放第三方开源社区或第三方厂家的程序,包括组件、工具、协议实现或对接平台的代码等
Kconfig Menuconfig配置文件,代码工程(如projects目录下的示例工程)中的Kconfig文件会引用此文件
SConscript OneOS操作系统使用Scons构建工具时的根编译脚本,该脚本会引用其它目录的SConscript脚本,若在OneOS操作系统根目录增加新的代码目录,需要修改此文件(参见“从零开始构建代码工程”章节)
LICENSE License 授权说明

工程目录介绍

打开OneOS目录下的projects文件夹,找到其中的stm32l475-cmcc-oneos文件夹,其文件列表如图所示:

oneos_project_files_list

目录或文件名称 描述
application 存放main及客户应用文件
board 存放STM32CubeMX工程、编译链接脚本、板级支持文件、启动文件等
.config 存放配置工具配置信息
.gitignore 配置工具文件
Kconfig 配置目录文件
oneos_config.h 工程配置宏定义头文件
osconfig.py 配置工具文件
project.uvoptx 工程配置信息
project.uvprojx 工程
SConscript 链接文件
SConstruct 链接文件
template.uvoptx demo工程配置信息
template.uvprojx demo工程

第一章 点亮RGB灯实验

1.1 简介

实验实现了RGB灯的循环闪烁。

1.2 硬件电路连接

RGB LED灯与MCU连接的引脚如下:

rgb_schematic

名称 管脚 作用
LED_R PE7 LED红灯控制引脚
LED_G PE8 LED绿灯控制引脚
LED_B PE9 LED蓝灯控制引脚

RGB_LED采用共阳极接法,单片机输出低电平LED亮,高电平LED灭;

rgb__schematic1

1.3 软件说明

RGB_LED程序源码在main.c文件中,创建的一个任务来运行RGB_LED程序,在程序中先对RGB连接的芯片IO配置为输出,然后在while循环中对3个灯依次进行开关,开和关之间间隔200ms。

RGB灯的引脚定义在board.c中,代码如下:

const led_t led_table[] = 
{
    {GET_PIN(E, 7), PIN_LOW},
    {GET_PIN(E, 8), PIN_LOW},
    {GET_PIN(E, 9), PIN_LOW},
};

const int led_table_size = ARRAY_SIZE(led_table);

main.c中RGB循环闪烁代码:

static void user_task(void *parameter)
{
    int i = 0;

    for (i = 0; i < led_table_size; i++)
    {
        os_pin_mode(led_table[i].pin, PIN_MODE_OUTPUT);
    }

    while (1)
    {
        for (i = 0; i < led_table_size; i++)
        {
            os_pin_write(led_table[i].pin, led_table[i].active_level);
            os_task_msleep(200);

            os_pin_write(led_table[i].pin, !led_table[i].active_level);
            os_task_msleep(200);
        }
    }

}

int main(void)
{
    os_task_t *task;

    task = os_task_create("user", user_task, NULL, 512, 3, 5);
    OS_ASSERT(task);    
    os_task_startup(task);

    return 0;
}

1.4 编译运行

编译成功后,下载程序到开发板,复位后重启开发板,观察开发板的运行效果,此时LED将循环闪烁。

rgb_board

1.5 注意

本文档中,所有实验均使用STM32L475VGT6核心板完成,如用户使用其他核心板进行开发,需要注意下管脚的对应关系。

第二章 串口使用实验

2.1 简介

本实验介绍了如何使用串口(UART2)实现数据的发送和接收,并介绍如何将串口(UART3)配置为OneOS的SHELL工具控制台,实时输出开发板的运行日志信息,实现人机交互,提高开发效率。

2.2 硬件说明

万耦开发板上,串口3通过USB转换,可实现与PC设备的便捷连接。

uart_to_usb_schematic

同时,将串口2引在JP2排母上,供用户使用。

uart2_schematic

名称 管脚 作用
PC4 PC4 UART3 TX引脚
PC5 PC5 UART3 RX引脚
EXT_USART_RX PD6 UART2 RX引脚
EXT_USART_TX PD5 UART2 TX引脚

串口在开发板上的位置如下图所示:

uart_position

2.3 软件说明

串口的测试代码在中\drivers\driver_test路径下:

static int serial_test(int argc, char *argv[])
{
    int           ret;
    int           tx_cnt;
    int           rx_cnt;
    unsigned char rx_buff[32];
    os_device_t  *uart;
    const char   *dev_name;

    if (argc != 2)
    {
        os_kprintf("usage: serial_test <dev> \r\n");
        os_kprintf("       serial_test uart2 \r\n");
        return -1;
    }

    dev_name = argv[1];

    uart = os_device_find(dev_name);
    OS_ASSERT(uart);

    /* Open serial device with rx nopoll flag */
    os_device_open(uart, OS_SERIAL_FLAG_RX_NOPOLL | OS_SERIAL_FLAG_TX_NOPOLL | OS_DEVICE_OFLAG_RDWR);

    struct serial_configure config = OS_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_115200;
    ret = os_device_control(uart, OS_DEVICE_CTRL_CONFIG, &config);
    if (ret != 0)
    {
        os_kprintf("serial control fail %d\r\n", ret);
        return -1;
    }

    os_task_msleep(1);

    /* Tx */
    tx_cnt = os_device_write(uart, 0, "Hello World!\n", sizeof("Hello World!\n"));

    /* Wait rx complete */
    os_task_msleep(100);

    /* Rx */
    rx_cnt = os_device_read(uart, 0, rx_buff, sizeof(rx_buff));

    os_kprintf("tx_cnt: %d, rx_cnt: %d\n", tx_cnt, rx_cnt);

    if (rx_cnt == sizeof("Hello World!\n"))
    {
        os_kprintf("rx buff:%s\n", rx_buff);
    }
    else
    {
        os_kprintf("rx failed\n");
    }

    os_device_close(uart);

    return 0;
}
SH_CMD_EXPORT(serial_test, serial_test, "serial_test");

2.4 编译运行

2.4.1 STM32CubeMX配置

在工程目录\board\CubeMX_Config下,打开STM32CubeMx工程STM32L475VG.ioc,并按照以下方式进行配置。

1.管脚设置

如图所示,此处以串口2的配置为例进行演示。根据原理图,将PD5,PD6设置为串口2功能引脚。

2.DMA设置

串口使用DMA进行数据收发有利于提高通信的效率,但用户可根据需求进行选择配置。

3.中断设置

在OneOS中串口默认采取中断方式进行数据接收,因此,需要使能串口中断。

4.参数设置

串口的初始化参数设置,设置波特率,数据长度,奇偶校验位等,一般采用默认设置。

5.保存设置并生成代码

2.4.2 OnsOS-Cube配置

OneOS物联网操作系统默认提供一个串口用于打印系统信息,使用前需要进行如下配置:

1、使能UART串口功能

除了在CubeMX工具中配置串口基本信息并生成代码,还需要在OneOS-Cube在工程中勾选使能串口功能。如图,在 Drivers→ Serial下使能串口功能,同时,根据实际需求,设置串口的缓存大小,默认情况下,收发的缓存大小都为64byte。

oneos_cube_uart1

2、选择控制台选择使用串口

在Kernel→ Kernel console路径下,设置控制台所用的串口。在万耦开发板中,我们一般选取串口3作为控制台串口。

3、添加演示代码

在Drivers→ Drivers samples路径下,添加串口演示代码。

设置完成后,使用ESC退出,然后选中Y保存配置。

2.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

2.4.4 运行

在工程目录在工程目录projects\stm32l475-cmcc-oneos中,打开工程project.uvprojx ,编译下载程序。打开了串口调试工具(波特率115200),输入help,可查看One OS的指令信息,如下:

sh>help
OneOS shell commands:
device           - show device information
pinMode          - set hardware pin mode
pinWrite         - write value to hardware pin
pinRead          - read status from hardware pin
event            - show event information
mb               - show mailbox information
memp             - show memory pool information
mem              - show memory usage information
mq               - show message queue information
mutex            - show mutex information
sem              - show semaphore information
task             - show task information
timer            - show timer information
version          - show oneos version
help             - Obtain help of commands

输入device命令,可查看当前系统中挂载了哪些设备。

sh>device
device                  type         ref count
--------------- -------------------- ----------
cortexm_systick ClockEvent Device    1
tim17           ClockEvent Device    0
uart3           Character Device     2
uart2           Character Device     0
uart1           Character Device     0
uart4           Character Device     0
cortexm_dwt     ClockSource Device   1
pin_0           Miscellaneous Device 0
sh>

至此,用户可通过控制台与开发板进行交互,即证明串口3已正常运行。

此时,将JP2的9,10号接口短接,对串口2进行回环测试。在控制台中,通过help指令可查看串口测试指令,然后再输入相应指令进行测试,如下:

sh>serial_test
usage: serial_test <dev>
       serial_test uart2
sh>serial_test uart2
tx_cnt: 14, rx_cnt: 14
rx buff:Hello World!
sh>serial_test uart2
tx_cnt: 14, rx_cnt: 14
rx buff:Hello World!
sh>serial_test uart2
tx_cnt: 14, rx_cnt: 14
rx buff:Hello World!
sh>serial_test uart2
tx_cnt: 14, rx_cnt: 14
rx buff:Hello World!
sh>

2.5注意

为了正常使用控制台与串口,还需要在OneOS-Cube中对以下项进行配置:

1、需要使能Driver下Timer功能;

timer作为嵌入式系统的重要组成部分,一般保持如图所示的默认状态即可。

2、需要使能components目录下的shell功能;

shell的配置可根据情况调整,如优先级,指令大小等。

第三章 按键实验

3.1 简介

本实验通过引脚的电平跳变触发中断实现按键功能,万耦一代开发板上,一共有5个按键,除了系统RESET键,其他键均可根据需求自己设计功能,如实现led灯的控制,蜂鸣器的控制等等。

3.2 硬件电路连接

按键的硬件原理连接如图所示,其中KEY1采用的是按键上拉方式,其他按键则采用下拉方式。

key_hardware

3.3 软件说明

为了方便使用,在push_button.h中定义了按键的类型结构体。

typedef struct push_button
{
    int pin;
    int mode;
    int irq_mode;
} push_button_t;

根据开发板按键的硬件设计,在board.c中创建按键表格对key1~key4进行统一管理。

const struct push_button key_table[] = 
{
    {GET_PIN(C, 13),    PIN_MODE_INPUT_PULLUP,      PIN_IRQ_MODE_FALLING},
    {GET_PIN(D, 10),    PIN_MODE_INPUT_PULLUP,      PIN_IRQ_MODE_FALLING},
    {GET_PIN(D, 9),     PIN_MODE_INPUT_PULLUP,      PIN_IRQ_MODE_FALLING},
    {GET_PIN(D, 8),     PIN_MODE_INPUT_PULLUP,      PIN_IRQ_MODE_FALLING},
};

按键测试程序key_test.c,主要功能是在运行测试程序后10s内按下如果按下按键就会输出当前的系统时钟计数和按键检测引脚电压。

static void pin_callback(void *args)
{
    os_kprintf("----------------------pin_callback:%d\r\n", (int)(unsigned long)args);
}

static int key_test(int argc, char *argv[])
{
    int i, j;

    for (i = 0; i < key_table_size; i++)
    {
        os_pin_mode(key_table[i].pin, key_table[i].mode);
        os_pin_attach_irq(key_table[i].pin, key_table[i].irq_mode, pin_callback, (void *)key_table[i].pin);
        os_pin_irq_enable(key_table[i].pin, PIN_IRQ_ENABLE);
    }

    for (j = 0; j < 10; j++)
    {
        for (i = 0; i < key_table_size; i++)
        {
            os_kprintf("<%u> pin : %d\r\n", (unsigned int)os_tick_get(), os_pin_read(key_table[i].pin));
        }

        os_task_mdelay(1000);
    }

    return 0;
}
SH_CMD_EXPORT(key_test, key_test, "key_test");

3.4 编译运行

3.4.1 STM32CubeMX配置

按键功能实现较简单,不用单独配置管脚功能。

3.4.2 OnsOS-Cube配置

1、使能按键功能

在Drivers→ MISC路径下,选中using push button device drivers:

2、添加演示代码

在Drivers→ Drivers samples路径下,添加按键演示代码。

3.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

3.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。

2、双击打开oneos\projects\stm32l475-cmcc-oneos\ project.uvprojx;

4、编译成功后烧写到设备,连接串口到电脑,打开串口工具,输入命令行指令key_test;

程序运行后,按下对应按键,会在控制台中显示其状态(高低电平),并触发中断。

sh />key_test
<25301> S[2] : 0
<25302> S[3] : 1
<25302> S[4] : 1
<25302> S[5] : 1
----------------------pin_callback:58
<25402> S[2] : 0
<25402> S[3] : 0
<25402> S[4] : 1
<25402> S[5] : 1
<25502> S[2] : 0
<25502> S[3] : 1
<25502> S[4] : 1
<25502> S[5] : 1
----------------------pin_callback:58
<25602> S[2] : 0
<25602> S[3] : 1
<25602> S[4] : 1
<25602> S[5] : 1
----------------------pin_callback:58
<25702> S[2] : 0
<25702> S[3] : 0
<25702> S[4] : 1
<25702> S[5] : 1
----------------------pin_callback:58
<25802> S[2] : 0
<25802> S[3] : 0
<25802> S[4] : 1
<25802> S[5] : 1
sh />

3.5 注意

Drivers→ MISC路径下的button,led,buzzer驱动必须勾选,否则代码编译会报错。

第四章 看门狗实验

4.1 简介

看门狗是程序运行错误的一个纠正机制,用来检测和解决由软件错误引起的故障;开始启用看门狗,为看门狗设置最大超时时间,当计数器计数到超时,会产生一个复位信号复位芯片。在超时之前重新激活(喂狗), 看门狗的超时值就会被重新加载到计数器,从而避免产生看门狗复位;本实验将介绍如何使用独立看门狗(IWDG)。

看门狗的溢出时间计算方式为:

$$ Tout=((42^p)r)/32

$$ 其中:Tout 为看门狗溢出时间(单位为 ms);2^p 为看门狗时钟预分频值(IWDG counter clock prescaler值),p值范围为 0~7;r为看门狗的重装载值(IWDG down-counter reload value 的值)。

4.2 硬件电路连接

独立看门狗是由芯片内部专门的低速时钟(LSI)驱动,即使主时钟发生故障,它也仍然有效。需要注意的是由于使用的内部时钟,所以时钟会有些偏差。

4.3 软件说明

看门狗测试程序源码位于\drivers\driver_test\ wdt_test.c中。在此处,看门狗不支持直接在代码中设置溢出时间,具体的时间需要用户在STM32CubeMX进行配置。

static int wdg_test(int argc, char *argv[])
{
    os_err_t    ret     = OS_EOK;
    os_uint32_t timeout = 10;
    char        device_name[OS_NAME_MAX];
    int         count = 0;
    os_device_t *wdg_dev;

    if (argc == 2)
    {
        strncpy(device_name, argv[1], OS_NAME_MAX);
    }
    else
    {
        strncpy(device_name, WDT_DEVICE_NAME, OS_NAME_MAX);
    }

    wdg_dev = os_device_find(device_name);
    if (!wdg_dev)
    {
        os_kprintf("find %s failed!\n", device_name);
        return OS_ERROR;
    }

    ret = os_device_init(wdg_dev);
    if (ret != OS_EOK)
    {
        os_kprintf("initialize %s failed!\n", device_name);
        return OS_ERROR;
    }

    ret = os_device_control(wdg_dev, OS_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
    if (ret != OS_EOK)
    {
        os_kprintf("%s not support set timeout!\n", device_name);
    }

    ret = os_device_control(wdg_dev, OS_DEVICE_CTRL_WDT_START, OS_NULL);
    if (ret != OS_EOK)
    {
        os_kprintf("start %s failed!\n", device_name);
        return OS_ERROR;
    }

    os_device_control(wdg_dev, OS_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
    while (count < 11)
    {
        os_task_mdelay(1000);
        count++;
        os_kprintf("watch dog keep alive for :%ds\n", count);
        os_device_control(wdg_dev, OS_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
    }
    count = 0;
    os_kprintf("\n");
    while (1)
    {
        os_kprintf("watch dog stop feed for :%d.%ds\n", count / 10, count % 10);
        os_task_mdelay(100);
        count++;
    }
}

SH_CMD_EXPORT(wdg_test, wdg_test, "test Independent watchdog!");

4.4 编译运行

4.4.1 STM32CubeMX配置

首先,需要在STM32CubeMX激活使能IWDG,然后在参数设置栏中设置相关参数。

其次,在需要在Project Manager→ Advanced Settings下,勾选不生成函数回调选项,否则工程上电后会不停的触发看门狗。

4.4.2 OnsOS-Cube配置

在Drivers→ WDG路径下,勾选上使用看门狗驱动选项,如下图所示:

选择看门狗测试用例:

选中后使用Q退出,然后选中Y保存配置

4.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

4.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。

2、双击打开oneos\projects\stm32l475-cmcc-oneos\ project.uvprojx;

3、编译成功后烧写到设备,连接串口到电脑,打开串口工具,在串口输入help,可以看到看门狗命令行指令wdt_test;

4、查看设备,可以看到wdt的设备:

sh>device
device                  type         ref count
--------------- -------------------- ----------
iwdg            Miscellaneous Device 0
uart3           Character Device     2
uart2           Character Device     0
uart1           Character Device     0
uart4           Character Device     0
cortexm_dwt     ClockSource Device   1
pin_0           Miscellaneous Device 0
sh>

5、输入help可以查看到我们新加入的测试程序wdt_test:


sh>help
OneOS shell commands:
wdg_test         - test Independent watchdog!
device           - show device information
pinMode          - set hardware pin mode
pinWrite         - write value to hardware pin
pinRead          - read status from hardware pin
event            - show event information
mb               - show mailbox information
memp             - show memory pool information
mem              - show memory usage information
mq               - show message queue information
mutex            - show mutex information
sem              - show semaphore information
task             - show task information
timer            - show timer information
version          - show oneos version
help             - Obtain help of commands
sh>

6、输入wdt_test运行测试程序,可以看到,8s后开发板就重启了;

sh>wdg_test
iwdg not support set timeout!
watch dog keep alive for :1s
watch dog keep alive for :2s
watch dog keep alive for :3s
...
...
watch dog stop feed for :0.0s
watch dog stop feed for :0.1s
watch dog stop feed for :0.2s
watch dog stop feed for :0.3s
...
watch dog stop feed for :7.6s
watch dog stop feed for :7.7s
watch dog stop feed for :7.8s
watch dog stop feed for :7.9s
watch dog stop feed for :8.0s
sh>

4.5 注意

1.因为独立看门狗使用的是内部时钟,所以时钟打印的结果可能会有些偏差。

2.看门狗溢出时间需要在STM32CubeMX中进行配置。

第五章 RTC实验

5.1 简介

在本实验中,我们将使用STM32L475 的内部实时时钟(RTC)实现日历功能。

5.2 硬件电路连接

STM32L475VGT6的RTC是一个独立的 BCD 定时器/计数器。RTC提供一个日历时钟(包含年月日时分秒信息)、两个可编程闹钟(ALARM A和 ALARM B)中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。两个32位寄存器(TR和DR)包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或24 小时制)、星期、日期、月份和年份。此外,还可提供二进制格式的亚秒值,自动将月份的天数补偿为 28、29(闰年)、30 和 31 天,进行夏令时补偿。RTC 模块和时钟配置是在后备区域,即在系统复位或从待机模式唤醒后RTC的设置和时间维持不变,只要后备区域供电正常,那么RTC将可以一直运行。

RTC_hardware

5.3 软件说明

RTC测试代码位于\drivers\driver_test\rtc_test中,用户可以手动设置日期与时间。

static int rtc_set_test(int argc, char *argv[])
{
    os_err_t ret = OS_EOK;
    time_t   now;

    /* Set date */
    ret = set_date(2020, 6, 1);
    if (ret != OS_EOK)
    {
        LOG_EXT_E("set RTC date failed %d", (int)ret);
        return ret;
    }
    os_task_mdelay(200);

    /* Set time */
    ret = set_time(9, 30, 0);
    if (ret != OS_EOK)
    {
        LOG_EXT_E("set RTC time failed %d", (int)ret);
        return ret;
    }

    os_task_mdelay(3000);

    /* Get time */
    now = rtc_get();
    os_kprintf("%s\n", ctime(&now));
    return ret;
}

SH_CMD_EXPORT(rtc_set_test, rtc_set_test, "set rtc time");

static void rtc_get_test(int argc, char *argv[])
{
    time_t now;

    /* Get time */
    now = rtc_get();

    os_kprintf("%s\n", ctime(&now));
}
SH_CMD_EXPORT(rtc_get_test, rtc_get_test, "get rtc time");

5.4 编译运行

5.4.1 STM32CubeMX配置

激活并设置RTC参数。

5.4.2 OnsOS-Cube配置

在Drivers→ RTC路径下,选择使用RTC驱动:

然后,和前面章节一样,在Drivers→ Drivers samples路径下,选择使用RTC测试用例。

选中后使用Q退出,然后选中Y保存配置

5.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

5.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。

2、双击打开oneos\projects\stm32l475-cmcc-oneos\ project.uvprojx;

3、编译成功后烧写到设备,连接串口到电脑,打开串口工具,输入help查看RTC测试指令;

sh>help
OneOS shell commands:
rtc_set_test     - set rtc time
rtc_get_test     - get rtc time
device           - show device information
pinMode          - set hardware pin mode
pinWrite         - write value to hardware pin
pinRead          - read status from hardware pin
event            - show event information
mb               - show mailbox information
memp             - show memory pool information
mem              - show memory usage information
mq               - show message queue information
mutex            - show mutex information
sem              - show semaphore information
task             - show task information
timer            - show timer information
version          - show oneos version
help             - Obtain help of commands
sh>

4、输入测试指令,查看结果。

sh>rtc_set_test
Mon Jun  1 09:30:02 2020

sh>rtc_get_test
Mon Jun  1 09:30:08 2020

sh>

5.5 注意

因为开发板上没有额外的电池进行持续性的供电,所以在开发板掉电后,RTC设置的日期与时间将不会保留,需要再次进行设置。

第六章 PWM输出实验

6.1简介

在本实验中,我们将使用一路 PWM 点亮LED 灯,并通过改变PWM占空比,调节LED灯的亮度。

6.2 硬件电路连接

呼吸灯D5连接到MCU的管脚上。

led_breath_schematic

led_breath_schematic1

管脚定义和作用:

名称 管脚 作用
Breath PD12 呼吸灯控制引脚

6.3 软件说明

在本实验中,使用TIMER4的channel1来输出PWM。测试代码位于\drivers\driver_test\pwm_test.c中,用户可以通过改变PWM的占空比,控制led灯的暗灭变换。

int pwm_sample(int argc, char **argv)
{
    os_uint32_t period = 5000000;  
    os_uint32_t pulse  = 1000000;      
    os_uint32_t channel;
    os_uint32_t pin;

    char *dev_name;
    os_pwm_device_t *pwm_dev = OS_NULL;


    if (argc < 3)
    {
        os_kprintf("usage: pwm_led_sample <dev> <channel> [period(ns)] [duty(ns) def 1000000] [pin]\r\n");
        os_kprintf("       pwm_led_sample pwm_tim1 1 default: 5000000, 1000000\r\n");
        os_kprintf("       pwm_led_sample pwm_tim1 1 5000000 1000000 0x3e\r\n");
        os_kprintf("       pwm_led_sample pwm_tim1 1 1000000000 1000000000 0x3e\r\n");
        os_kprintf("       pwm_led_sample pwm_tim1 1 1000000000 0 0x3e\r\n");
        return -1;
    }

    dev_name = argv[1];
    channel  = strtol(argv[2], OS_NULL, 0);

    if (argc > 3)
    {
        period = strtol(argv[3], OS_NULL, 0);
    }

    if (argc > 4)
    {
        pulse = strtol(argv[4], OS_NULL, 0);
    }

    if (argc > 5)
    {
        pin = strtol(argv[5], OS_NULL, 0);

        os_pin_mode(pin, PIN_MODE_INPUT_PULLUP);
        os_pin_attach_irq(pin, PIN_IRQ_MODE_RISING_FALLING, pwm_pin_callback, (void *)pin);
        os_pin_irq_enable(pin, PIN_IRQ_ENABLE);
    }

    pwm_dev = (os_pwm_device_t *)os_device_find(dev_name);
    if (pwm_dev == OS_NULL)
    {
        os_kprintf("pwm sample run failed! can't find %s device!\n", dev_name);
        return OS_ERROR;
    }

    os_pwm_set_period(pwm_dev, channel, period);

    os_pwm_set_pulse(pwm_dev, channel, pulse);

    os_pwm_enable(pwm_dev, channel);

    return 0;
}

SH_CMD_EXPORT(pwm_sample, pwm_sample, "test_pwm_sample!");

6.4 编译运行

6.4.1 STM32CubeMX配置

根据电路原理图定位到呼吸灯使用的是TIMER4的1号通道,因此,其配置如下:

6.4.2 OnsOS-Cube配置

在Drivers→ MISC路径下,勾选使用PWM设备驱动。

然后在Drivers→ Drivers samples路径下,选择使用PWM测试用例。

选中后使用Q退出,然后选中Y保存配置。

6.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

6.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。

2、双击打开oneos\projects\stm32l475-cmcc-oneos\ project.uvprojx;

3、编译成功后烧写到设备,连接串口到电脑,打开串口工具;

输入指令device,查看pwm设备是否已注册到设备框架中。

sh>device
device                  type         ref count
--------------- -------------------- ----------
cortexm_systick ClockEvent Device    1
rtc             RTC                  0
pwm_tim4        Miscellaneous Device 0
uart3           Character Device     2
uart2           Character Device     0
uart1           Character Device     0
uart4           Character Device     0
cortexm_dwt     ClockSource Device   1
pin_0           Miscellaneous Device 0
sh>

输入pwm_sample测试指令,可看到呼吸灯由亮变暗,直到熄灭。

sh>pwm_sample
usage: pwm_led_sample <dev> <channel> [period(ns)] [duty(ns) def 1000000] [pin]
       pwm_led_sample pwm_tim1 1 default: 5000000, 1000000
       pwm_led_sample pwm_tim1 1 5000000 1000000 0x3e
       pwm_led_sample pwm_tim1 1 1000000000 1000000000 0x3e
       pwm_led_sample pwm_tim1 1 1000000000 0 0x3e
sh>pwm_sample pwm_tim4 1
sh>
sh>pwm_sample pwm_tim4 1 5000000 2000000
sh>
sh>pwm_sample pwm_tim4 1 5000000 3000000
sh>
sh>pwm_sample pwm_tim4 1 5000000 4000000
sh>
sh>pwm_sample pwm_tim4 1 5000000 5000000
sh>

6.5 注意

呼吸灯D5的位置,处于RGB灯的正下方。

第七章 传感器实验

7.1 简介

本实验主要介绍了如何使用万耦开发板底板上的三个传感器(AP3216C,AHT10与ICM20602),并利用I2C总线实现通信,读取相应的传感器数据。其中,AP3216C芯片集成了环境光的强度(ALS, ambient light sensor)检测和接近感应(PS,proximity sensor),AHT10芯片集成了温度和湿度检测,ICM20602集成了三轴加速度计(three accelerater)与三轴陀螺仪(three gyroscoper)。

以上传感器和MCU之间均通过I2C通信,更多芯片相关信息请查阅芯片手册。

7.2 硬件电路连接

万耦开发板底板上的三个传感器挂载到了同一个I2C总线(I2C3)上。

1、AP3216C光强传感器原理图

AP3216C_schematic

2、AHT10温湿度传感器原理图

3、ICM20602六轴传感器原理图

主要管脚定义和作用:

名称 管脚 作用
I2C_SDA3 PC1 I2C3的数据引脚
I2C_SCL3 PC0 I2C3的时钟控制引脚

如图所示,三个传感器位于开发板的右下角:

7.3 软件说明

AP3216C芯片相关驱动在sensors文件夹下的ap3216c.c文件中,通过统一的sensors框架进行封装,用户可以通过sensors框架提供的外层接口直接获得芯片读出的光强和距离感应值。

以AP3216C为例,sensors实现框架的函数结构如图表所示: | 函数名 | 用途 | | -------- | ------------------ | | os_hw_ap3216c_light_init | 初始化传感器光强功能 | | os_hw_ap3216c_proximity_init | 初始化传感器距离感应功能 | | ap3216c_init | 初始化芯片相关信息,总线及芯片地址等 | | ap3216c_proximity_control | 距离感应相关功能控制 | | ap3216c_fetch_proximity_data | 获取距离数据 | | ap3216c_light_control | 光强感应相关功能控制 | | ap3216c_fetch_light_data | 获取光强数据 |

以AP3216C光强传感器为例,sensors接口框架如下列代码所示,实现和底层芯片型号分离,只需要传入对应的芯片名称,即可正确读写芯片数据。

static int sensor_light_test(int argc, char *argv[])
{
    int  i;
    char sensor_name[24];
    struct os_sensor_data sensor_data;

    if (argc != 2)
    {
        os_kprintf("usage:sensor_light_test <sensor_name>\r\n");
        return -1;
    }

    snprintf(sensor_name, sizeof(sensor_name) - 1, "li_%s", argv[1]);

    os_device_t *sensor = os_device_find(sensor_name);
    OS_ASSERT(sensor != NULL);
    os_device_open(sensor, OS_DEVICE_FLAG_RDWR);

    struct os_sensor_info sensor_info;
    os_device_control(sensor, OS_SENSOR_CTRL_GET_INFO, &sensor_info);

    for (i = 0; i < 10; i++)
    {
        os_device_read(sensor, 0, &sensor_data, sizeof(struct os_sensor_data));

        if (sensor_info.unit == OS_SENSOR_UNIT_MLUX)
        {
            os_kprintf("sensor light (%d.%03d)\r\n", sensor_data.data.light / 1000, sensor_data.data.light % 1000);
        }
        else if (sensor_info.unit == OS_SENSOR_UNIT_LUX)
        {
            os_kprintf("sensor light (%d)\r\n", sensor_data.data.light);
        }
        else
        {
            os_kprintf("invalid unit\r\n");
        }

        os_task_mdelay(1000);
    }

    return 0;
}
SH_CMD_EXPORT(sensor_light_test, sensor_light_test, "sensor_light_test");

ATH10芯片相关驱动在sensors文件夹下的aht10.c文件中,通过统一的sensors框架进行封装,用户可以通过sensors框架提供的外层接口直接获得传感器芯片检测到的温度和湿度数据。详细说明可以参考AP3216C芯片。

ICM20602芯片相关驱动在OneOS根目录thirdparty\mpu6xxx文件夹下的sensor_inven_mpu6xxx.c,mpu6xxx.c文件中,通过统一的sensors框架进行封装,用户可以通过sensors框架提供的外层接口直接获得传感器检测到的数据。

7.4 编译运行

7.4.1 STM32CubeMX配置

万耦开发板传感器实验中,传感器均采用软件模拟i2c的方式实现交互,因此,不必在STM32CubeMX中进行i2c的硬件配置。

7.4.2 OnsOS-Cube配置

1、配置模拟I2C的引脚信息,万耦开发板中,传感器设备都使用i2c3接口。

如图,在Drivers → I2C路径下,需要使能i2c设备驱动,勾选使用模拟i2c,设置i2c总线延时(调节软件i2c的频率)并使能i2c3总线。

2、配置模拟i2c管脚。

3、在 Drivers→ Sensors→ Using sensor device drivers → Enable ap3216c路径下,以打开光感传感器配置,配置传感器使用的i2C接口为soft_I2c3,地址是0x1e。

同理,配置AHT10传感器:

ICM20602传感器配置稍微有所区别,其配置方式如下图所示:

4、选择测试用例。

选中后使用Q退出,然后选中Y保存配置。

7.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

7.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。

2、双击打开oneos\projects\stm32l475-cmcc-oneos\ project.uvprojx;

3、编译成功后烧写到设备,连接串口到电脑,打开串口工具;

输入help指令,可看到此时多了传感器的测试指令。

sh>help
OneOS shell commands:
sensor_acce_test - sensor_acce_test
sensor_alti_test - sensor_alti_test
sensor_baro_test - sensor_baro_test
sensor_gyro_test - sensor_gyro_test
sensor_humi_test - sensor_humi_test
sensor_light_test - sensor_light_test
sensor_temp_test - sensor_temp_test
device           - show device information
pinMode          - set hardware pin mode
pinWrite         - write value to hardware pin
pinRead          - read status from hardware pin
event            - show event information
mb               - show mailbox information
memp             - show memory pool information
mem              - show memory usage information
mq               - show message queue information
mutex            - show mutex information
sem              - show semaphore information
task             - show task information
timer            - show timer information
version          - show oneos version
help             - Obtain help of commands
sh>

通过指令查看设备,此时能看到已经配置好的soft_i2c3总线与传感器:

sh>device
device                  type         ref count
--------------- -------------------- ----------
gyro_icm20602   Sensor Device        0
acce_icm20602   Sensor Device        0
pr_ap3216c      Sensor Device        0
li_ap3216c      Sensor Device        0
humi_aht10      Sensor Device        0
temp_aht10      Sensor Device        0
soft_i2c3       I2C Bus              0
cortexm_systick ClockEvent Device    1
rtc             RTC                  0
uart3           Character Device     2
uart2           Character Device     0
uart1           Character Device     0
uart4           Character Device     0
cortexm_dwt     ClockSource Device   1
pin_0           Miscellaneous Device 0
sh>

4、输入传感器测试指令;

如下所示,用手电照射光强传感器时,随着距离接近,光照更强,读数变大。

sh>sensor_light_test ap3216c
sensor light (182.700)
sensor light (180.600)
sensor light (177.100)
sensor light (179.200)
sensor light (211.750)
sensor light (246.050)
sensor light (300.650)
sensor light (427.350)
sensor light (488.250)
sensor light (564.200)
sh>

如下所示,当将手指放在温湿度传感器上时(或对着温度传感器呼气),温度会有缓慢升高。

sh>sensor_temp_test aht10
sensor temp (24.841)
sensor temp (24.860)
sensor temp (25.620)
sensor temp (26.413)
sensor temp (26.943)
sensor temp (27.363)
sensor temp (27.720)
sensor temp (27.937)
sensor temp (27.755)
sensor temp (27.505)
sh>

7.5 注意

7.5.1 硬件I2C配置

本章节使用的是软件模拟I2C,如果需要使用硬件I2C,则需要配置STM32CubeMX;

同时,OnsOS-Cube的配置方式也有所不同,如下:

7.5.2 管脚编号

在本章7.4.2小结中,配置了I2C3的SCL与SDA引脚编号,此编号与实际引脚名称的对应关系如下表:

MCU管脚 编号
PA0 0
PA1 1
... ...
PA15 15
PB0 16
PB15 31
PC0 32
PC15 47
PD0 48
PD15 63
PE0 64
PE15 79
PF0 80
... ...

PA0对应编号0 ,PA1对应编号1,后面管脚号以此类推。

第八章 红外发送和接收实验

8.1 简介

本实验通过开发板上的红外发送和接收装置实现红外的发送和接收,其原理是通过GPIO外部中断,记录红外信号上、下边沿的时间戳,然后根据高低脉冲宽度,解码出红外信息,实现红外通信功能。

8.2 硬件电路连接

红外的发送和接收电路图如下:

infrared_schematic1

infrared_schematic2

红外接收和发送引脚连接到了MCU的引脚上。

infrared_schematic3

管脚定义和作用:

名称 管脚 作用
RECEPTION_OUT PB1 红外接收器
EMISSION PB0 红外发送器

红外发送器和接收器在开发板中的位置:

infrared_board

8.3 软件说明

红外设备的测试代码位于\drivers\driver_test\infrared_test.c中,其创建了一个红外接收任务处理红外信号的接收与解析。

static void infrared_recv_task(void *parameter)
{
    os_device_t *infrared;
    struct os_infrared_info info;
    int infrared_rx_count = 0;

    infrared = os_device_find("atk_rmt");
    OS_ASSERT(infrared);

    os_device_open(infrared, OS_DEVICE_OFLAG_RDWR);

    while (1)
    {
        os_device_read(infrared, 0, &info, sizeof(info));
        LOG_EXT_I("infrared_rx_done(%d) addr: %02x, data: %02x", ++infrared_rx_count, info.addr, info.data);
    }
}

static int infrared_recv_test(void)
{
    os_task_t *task;

    task = os_task_create("ir_recv", infrared_recv_task, NULL, 2048, 3, 5);
    OS_ASSERT(task);
    os_task_startup(task);

    return 0;
}

static int infrared_send_test(int argc, char **argv)
{
    os_uint8_t addr = 0x5a;
    os_uint8_t data = 0x3c;
    int i, repeat, loops = 1;

    if (argc == 1 || (argc == 2 && !strcmp(argv[1], "help")))
    {
        LOG_EXT_I("usage:");
        LOG_EXT_I("infrared_send_test [addr] [data] [repeat] [loops]");
        return 0;
    }

    if (argc > 1)
    {
        addr = strtol(argv[1], NULL, 0);
    }

    if (argc > 2)
    {
        data = strtol(argv[2], NULL, 0);
    }

    if (argc > 3)
    {
        repeat = strtol(argv[3], NULL, 0);
    }

    if (argc > 4)
    {
        loops = strtol(argv[4], NULL, 0);
    }

    os_device_t *infrared;
    struct os_infrared_info info;

    infrared = os_device_find("atk_rmt");
    OS_ASSERT(infrared);

    os_device_open(infrared, OS_DEVICE_OFLAG_RDWR);

    os_uint8_t task_priority = 1;
    os_task_control(os_task_self(), OS_TASK_CTRL_CHANGE_PRIORITY, &task_priority);

    for (i = 0; i < loops; i++)
    {
        os_task_msleep(1000);

        info.addr  = addr;
        info.data  = data + i;
        info.times = repeat;
        os_device_write(infrared, 0, &info, sizeof(info));
    }

    os_device_close(infrared);

    return 0;
}

SH_CMD_EXPORT(infrared_recv_test, infrared_recv_test, "infrared_recv_test");
SH_CMD_EXPORT(infrared_send_test, infrared_send_test, "infrared_send_test");

8.4 编译运行

8.4.1 STM32CubeMX配置

因为红外传感器使用到的是GPIO接口较为简单,所以不必单独使用STM32CubeMX进行配置。

8.4.2 OnsOS-Cube配置

Drivers→ Infrared路径下,配置红外设备的信息;

同时,还需要配置红外接收与发送引脚。

1)配置发送引脚:

2)配置接收引脚:

最后,在Drivers→ Drivers samples下选择使用红外设备驱动测试用例。

选中后使用Q退出,然后选中Y保存配置。

8.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令scons --ide=mdk5编译生成keil工程。

8.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。

2、双击打开oneos\projects\stm32l475-cmcc-oneos\ project.uvprojx;

3、编译成功后烧写到设备,连接串口到电脑,打开串口工具;

输入infrared_test运行测试程序,使用红外遥控器对着开发板上的红外接收器按下按钮(或者直接在命令行中输入infrared_send_test 命令),红外接收器接收到信号后打印出相应结果。

sh>infrared_recv_test
[2473] I/infrared: infrared start receive [infrared_recv_init][303]
[66022] I/infrared_test: usage: [infrared_send_test][71]
[66022] I/infrared_test: infrared_send_test [addr] [data] [repeat] [loops] [infrared_send_test][72]
sh>infrared_send_test 0 100 1
sh>[3147] I/infrared_test: infrared_rx_done(1) addr: 00, data: 64 [infrared_recv_task][48]
[3148] I/infrared_test: infrared_rx_done(2) addr: 00, data: 64 [infrared_recv_task][48]
sh>infrared_send_test 0 60 1
sh>[62551] I/infrared_test: infrared_rx_done(3) addr: 00, data: 3c [infrared_recv_task][48]
[62552] I/infrared_test: infrared_rx_done(4) addr: 00, data: 3c [infrared_recv_task][48]

8.5 注意事项

在使用红外接收器时,因为其接收特性,需要将dlog的选项调整一下,否则无法在控制台中看见红外打印信息。

在Debug路径下,需要打开 Debug功能。

在Components→ Dlog下,调整记录等级为Information。

第九章 LCD显示实验

9.1 简介

本实验主要介绍了如何在万耦一代开发板上使用 LCD。

9.2 硬件说明

万耦一代板载一块1.3寸的LCD显示屏,分辨率为240*240,显示效果十分细腻。显示屏的驱动芯片是ST7789,通过4-line SPI接口和单片机进行通讯。如图,LCD屏幕通过J8转接口连接到开发板上,因为只需要往LCD写数据而不需要读取,所以可以不接 MISO 引脚。

LCD

如电路原理图,处理器通过图示管脚来控制LCD,每个管脚作用如下表:

名称 管脚 作用
TFT_SPICLK PA5 SP1时钟信号
TFT_SPIMOSI PA7 SPI1数据信号
TFT_RES PA6 LCD复位信号
TFT_DC PD11 LCD命令/数据选择信号
TFT_BLK PA4 LCD背光控制信号

9.3 软件说明

LCD的驱动代码在/graphic/st7789vw.c文件中,其初始化代码如下所示:

static int os_hw_lcd_init(void)
{
    lcd_gpio_init();
    os_hw_spi_device_attach(OS_ST7789VW_SPI_BUS_NAME, OS_ST7789VW_SPI_BUS_NAME "_lcd", OS_ST7789VW_SPI_CS_PIN);
    os_hw_lcd_config();

    /* Memory Data Access Control */
    lcd_write_cmd(0x36);
    lcd_write_data(0x00);
    /* RGB 5-6-5-bit  */
    lcd_write_cmd(0x3A);
    lcd_write_data(0x65);
    /* Porch Setting */
    lcd_write_cmd(0xB2);
    lcd_write_data(0x0C);
    lcd_write_data(0x0C);
    lcd_write_data(0x00);
    lcd_write_data(0x33);
    lcd_write_data(0x33);
    /*  Gate Control */
    lcd_write_cmd(0xB7);
    lcd_write_data(0x35);
    /* VCOM Setting */
    lcd_write_cmd(0xBB);
    lcd_write_data(0x19);
    /* LCM Control */
    lcd_write_cmd(0xC0);
    lcd_write_data(0x2C);
    /* VDV and VRH Command Enable */
    lcd_write_cmd(0xC2);
    lcd_write_data(0x01);
    /* VRH Set */
    lcd_write_cmd(0xC3);
    lcd_write_data(0x12);
    /* VDV Set */
    lcd_write_cmd(0xC4);
    lcd_write_data(0x20);
    /* Frame Rate Control in Normal Mode */
    lcd_write_cmd(0xC6);
    lcd_write_data(0x0F);
    /* Power Control 1 */
    lcd_write_cmd(0xD0);
    lcd_write_data(0xA4);
    lcd_write_data(0xA1);
    /* Positive Voltage Gamma Control */
    lcd_write_cmd(0xE0);
    lcd_write_data(0xD0);
    lcd_write_data(0x04);
    lcd_write_data(0x0D);
    lcd_write_data(0x11);
    lcd_write_data(0x13);
    lcd_write_data(0x2B);
    lcd_write_data(0x3F);
    lcd_write_data(0x54);
    lcd_write_data(0x4C);
    lcd_write_data(0x18);
    lcd_write_data(0x0D);
    lcd_write_data(0x0B);
    lcd_write_data(0x1F);
    lcd_write_data(0x23);
    /* Negative Voltage Gamma Control */
    lcd_write_cmd(0xE1);
    lcd_write_data(0xD0);
    lcd_write_data(0x04);
    lcd_write_data(0x0C);
    lcd_write_data(0x11);
    lcd_write_data(0x13);
    lcd_write_data(0x2C);
    lcd_write_data(0x3F);
    lcd_write_data(0x44);
    lcd_write_data(0x51);
    lcd_write_data(0x2F);
    lcd_write_data(0x1F);
    lcd_write_data(0x1F);
    lcd_write_data(0x20);
    lcd_write_data(0x23);
    /* Display Inversion On */
    lcd_write_cmd(0x21);
    /* Sleep Out */
    lcd_write_cmd(0x11);

    /* wait for power stability */
    os_task_mdelay(100);

    lcd_clear(WHITE);

    /* display on */
    lcd_display_on();

    lcd_write_cmd(0x29);

    return OS_EOK;
}
OS_DEVICE_INIT(os_hw_lcd_init);

测试代码位于/graphic/graphic.c中,如下:

static os_err_t graphic_test(int argc, char **argv)
{
    if (argc != 2)
    {
        os_kprintf("usage: graphic_test <dev> \r\n");
        os_kprintf("       graphic_test lcd \r\n");
        return -1;
    }

    os_device_graphic_t *graphic;
    graphic = (os_device_graphic_t *)os_device_find(argv[1]);

    if (graphic == NULL || graphic->parent.type != OS_DEVICE_TYPE_GRAPHIC)
    {
        os_kprintf("invalide graphic device [%s].\r\n", argv[1]);
        return OS_EINVAL;
    }

    if (graphic->info.pixel_format == OS_GRAPHIC_PIXEL_FORMAT_ARGB888)
    {
        return graphic_test_888(graphic);
    }

    if (graphic->info.pixel_format == OS_GRAPHIC_PIXEL_FORMAT_RGB565)
    {
        return graphic_test_565(graphic);
    }

    return OS_EINVAL;
}

SH_CMD_EXPORT(graphic_test, graphic_test, "graphic_test");

9.4 编译运行

9.4.1 STM32CubeMX配置

由原理图可知,万耦开发板中LCD显示屏用到了SPI1作为交互的接口,因此在STM32CubeMX只对SPI1进行配置即可。

如下图,可将SPI1的模式设置为Half-Duplex Master模式。

SPI1的基本参数设置。

9.4.2 OnsOS-Cube配置

使用LCD屏幕前需要进行如下配置:

首先,需要在Drivers→ Graphic路径下,选择使用图像设备驱动。

然后,在显示设备中对LCD 驱动芯片st7789进行配置,其路径:Drivers -> Graphic ->Using Graphic devices ->Use st7789。

选中后使用Q退出,然后选中Y保存配置

9.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

9.4.4 运行

使用keil5打开工程project.uvprojx ,编译下载程序。

输入图形设备的测试指令后,LCD以红,绿,蓝等颜色进行刷屏。

graphic_test
sh />graphic_test
usage: graphic_test <dev>
       graphic_test lcd
sh />graphic_test lcd
red
green
blue
black
white
sh />

9.5 注意事项

1.LCD连接到开发板的SPI片选信号内部拉低(低电平有效),因此没有将SPI片选信号外接出来。

2.屏幕的分辨率是240*240,输入位置参数时要注意小于240,不然会出现无法显示的现象。

3.图像的取模方式为自上而下,自左向右,高位在前,16位色(RGB-565)。

第十章 USB鼠标实验

10.1 简介

本实验使用万耦开发板USB设备接口连接PC机,并将开发板设备作为鼠标进而控制桌面鼠标移动。

10.2 硬件说明

本实验主要用到的是USB接口,其硬件设计如下图所示:

usb_hardware

名称 管脚 作用
USB_DM PA11 USB DM引脚
USB_DP PA12 USB DP引脚

USB设备接口在开发板上的位置:

usb_otg_position

10.3 软件说明

USB设备在运行时,会创建一个任务进行USB数据的处理,相关代码位于drivers\usb\usbdevice\core\core.c中,如下:

os_err_t os_usbd_core_init(void)
{
    os_list_init(&device_list);

    /* Create an usb message queue */
    os_mq_init(&usb_mq, "usbd", usb_mq_pool, sizeof(usb_mq_pool), USBD_MQ_MSG_SZ, OS_IPC_FLAG_FIFO);

    /* Init usb device task */
    os_task_init(&usb_task,
                 "usbd",
                 os_usbd_task_entry,
                 OS_NULL,
                 usb_task_stack,
                 OS_USBD_TASK_STACK_SZ,
                 OS_USBD_TASK_PRIO,
                 20);
    /* os_task_init should always be OK, so start the task without further
     * Checking. */
    return os_task_startup(&usb_task);
}

USB鼠标测试代码位于drivers\driver_test\usbd_hid_test.c中,运行测试代码后,桌面鼠标光标会按矩形路径自动移动5圈。

static int usbd_hid_test(int argc, char **argv)
{
    int          i, j;
    os_device_t *device = os_device_find("hidd");
    OS_ASSERT(device != OS_NULL);
    os_device_open(device, OS_DEVICE_FLAG_WRONLY);

    /* Mouse left button */
    if (key_table_size > 0)
    {
        os_pin_mode(key_table[0].pin, key_table[0].mode);
        os_pin_attach_irq(key_table[0].pin, key_table[0].irq_mode, left_callback, NULL);
        os_pin_irq_enable(key_table[0].pin, PIN_IRQ_ENABLE);
    }

    /* Mouse right button */
    if (key_table_size > 1)
    {
        os_pin_mode(key_table[1].pin, key_table[1].mode);
        os_pin_attach_irq(key_table[1].pin, key_table[1].irq_mode, right_callback, NULL);
        os_pin_irq_enable(key_table[1].pin, PIN_IRQ_ENABLE);
    }

    for (j = 0; j < 5; j++)
    {
        os_kprintf("loop %d/5\r\n", j + 1);

        for (i = 0; i < 20; i++)
        {
            x = 10;
            y = 0;
            update_mouse(device);
            os_task_msleep(100);
        }

        for (i = 0; i < 20; i++)
        {
            x = 0;
            y = 10;
            update_mouse(device);
            os_task_msleep(100);
        }

        for (i = 0; i < 20; i++)
        {
            x = -10;
            y = 0;
            update_mouse(device);
            os_task_msleep(100);
        }

        for (i = 0; i < 20; i++)
        {
            x = 0;
            y = -10;
            update_mouse(device);
            os_task_msleep(100);
        }
    }

    return 0;
}

10.4 编译运行

10.4.1 STM32CubeMX配置

1、使能USB接口并配置USB接口模式,引脚。

2、配置USB接口的基本参数。

3、配置USB接口中断。

10.4.2 OnsOS-Cube配置

在Drivers→ USB路径下配置好USB设备,具体配置如下图所示:

10.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

10.4.4 运行

1、运行代码后,使用device指令,可查看usbd是否成功注册到设备框架中。

sh />device
device                type         ref count
------------- -------------------- ----------
hidd          Character Device     0
usbd          USB Slave Device     0
uart3         Character Device     2
pin           Miscellaneous Device 0
sh />

2、打开PC机设备管理器,此时,可看到有两个鼠标设备。

usb_setup

3、执行测试代码,此时鼠标会自动开始在屏幕上沿顺时针方向矩形运动。

sh />usbd_hid_test
loop 1/5
loop 2/5
loop 3/5
loop 4/5
loop 5/5

第十一章 FAL读写FLASH实验

11.1 简介

本实验通过FAL软件包对Flash进行分区管理操作。通过调用FAL接口完成了对指定分区的测试工作,完成了对Flash读、写、擦的测试,同时也通过本实验完成了对Flash驱动的基本测试。

11.2 硬件说明

本开发板在核心板上外拓展了一块W25Q64的flash芯片,大小为8MB,通过QSPI1接口与处理器相连。

QSPI_FLASH_schematic

如电路原理图,各个管脚作用如下表:

名称 管脚 作用
QSPI1_BK1_NCS PE11 QSP1时钟信号
QSPI1_BK1_IO1 PE13 QSPI1数据信号
QSPI1_BK1_IO0 PE12 LCD复位信号
QSPI1_BK1_CLK PE10 LCD命令/数据选择信号
QSPI1_BK1_IO3 PE15 QSPI1数据信号
QSPI1_BK1_IO2 PE14 QSPI1数据信号

11.3 软件说明

本实验包含QSPI接口、fal软件包、sfud库。fal软件包统一管理片内和片外flash,通过sfud使用QSPI接口对接片外flash。用户可以通过fal便捷的管理flash,客户如果基于框架进行自己开发其他flash芯片时需要注意flash芯片是否被sfud支持,详细的实现过程请查看源码中的fal和sfud软件包。

fal测试代码在driver/driver_test目录下。

static void fal(int argc, char **argv)
{
    if (argc < 3)
    {
help:
        os_kprintf("\n");
        os_kprintf("fal [OPTION] [PARAM ...]\n");
        os_kprintf("    read       <part> <off> <len>  Read <len> Bytes from <off> of <part>\n");
        os_kprintf("    write      <part> <off> <len>  Write <len> Bytes from <off> of <part>\n");
        os_kprintf("    erase      <part> <off> <len>  Erase <len> Bytes from <off> of <part>\n");
        os_kprintf("    eraseall   <part>              Erase all data on <part>\n");
        os_kprintf("    write_read <part> <off> <len>  Write & Read <len> Bytes from <off> of <part>\n");
        os_kprintf("    lock       <part>              Lock <part>\n");
        os_kprintf("    unlock     <part>              Unlock <part>\n");
        os_kprintf("    mount      <part> [dir] [fs]   Mount <part> [/] [fat, jffs2]\n");
        return;
    }

    if (!strcmp(argv[1], "read"))
    {
        if (argc < 5)
        {
            os_kprintf("The input parameters are too few!\n");
            goto help;
        }
        fal_read(argv[2], strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0));
    }
    else if (!strcmp(argv[1], "write"))
    {
        if (argc < 5)
        {
            os_kprintf("The input parameters are too few!\n");
            goto help;
        }
        fal_write(argv[2], strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0));
    }
    else if (!strcmp(argv[1], "erase"))
    {
        if (argc < 5)
        {
            os_kprintf("The input parameters are too few!\n");
            goto help;
        }
        fal_erase(argv[2], strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0));
    }
    else if (!strcmp(argv[1], "eraseall"))
    {
        fal_erase_all(argv[2]);
    }
    else if (!strcmp(argv[1], "write_read"))
    {
        if (argc < 5)
        {
            os_kprintf("The input parameters are too few!\n");
            goto help;
        }
        fal_write_read(argv[2], strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0));
    }
    else if (!strcmp(argv[1], "lock"))
    {
        fal_lock(argv[2]);
    }
    else if (!strcmp(argv[1], "unlock"))
    {
        fal_unlock(argv[2]);
    }
    else if (!strcmp(argv[1], "mount"))
    {
        const char *dir = "/";
        const char *fs  = "fat";

        if (argc >= 4)
            dir = argv[3];

        if (argc >= 5)
            fs = argv[4];

        fal_mount(argv[2], dir, fs);
    }
    else
    {
        os_kprintf("Input parameters are not supported!\n");
        goto help;
    }
}

SH_CMD_EXPORT(fal, fal, "fal test");

11.4 编译运行

11.4.1 STM32CubeMX配置

配置QSPI接口模式与引脚。

配置QSPI基本参数。

11.4.2 OnsOS-Cube配置

1、配置flash相关接口

在Drivers → SPI路径下,使能QSPI模式,以及其他相关信息。

2、配置QSPI总线

在Using QSPI mode support路径下配置总线名称。

3、配置片外flash信息

在 Extern flash sfud port cfg路径下配置FLASH的信息。

4、配置使能FAL工具

5、选择测试用例

最后使用Q退出,然后选中Y保存配置。

11.4.3 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

11.4.4 运行

1、使用keil5打开工程project.uvprojx ,编译下载程序。 2、通过shell命令进行flash测试。 3、查看设备。

通过shell指令查看当前设备,可看到W25Q64块设备,qspi总线设备等。


sh>device
device                  type         ref count
--------------- -------------------- ----------
W25Q64          Block Device         0
sfud_bus        SPI Device           0
cortexm_systick ClockEvent Device    1
qspi            SPI Bus              0
uart3           Character Device     2
uart2           Character Device     0
uart1           Character Device     0
uart4           Character Device     0
cortexm_dwt     ClockSource Device   1
pin_0           Miscellaneous Device 0
sh>

4、使用fal测试指令对flash进行读写。

测试时,可先使用read读出一段flash的值,再进行write操作(需要确认当前段是否可进行write),然后回读查看write是否成功。最后,对其进行erase后再回读,查看erase是否成功。

sh>fal
fal [OPTION] [PARAM ...]
    read       <part> <off> <len>  Read <len> Bytes from <off> of <part>
    write      <part> <off> <len>  Write <len> Bytes from <off> of <part>
    erase      <part> <off> <len>  Erase <len> Bytes from <off> of <part>
    eraseall   <part>              Erase all data on <part>
    write_read <part> <off> <len>  Write & Read <len> Bytes from <off> of <part>
    lock       <part>              Lock <part>
    unlock     <part>              Unlock <part>
    mount      <part> [dir] [fs]   Mount <part> [/] [fat, jffs2]
sh>
sh>fal read easyflash 0 100
part page size: 0x1000, erase size:0x1000, size:0x80000
read offset:0x0 count=100/100
read success
00000000: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000010: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000020: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000030: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000040: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000050: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000060: ff ff ff ff
sh>
sh>fal write easyflash 0 100
part page size: 0x1000, erase size:0x1000, size:0x80000
write offset:0x0 count=100/100
write success
sh>fal read easyflash 0 100
part page size: 0x1000, erase size:0x1000, size:0x80000
read offset:0x0 count=100/100
read success
00000000: 00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f
00000010: 10 11 12 13 14 15 16 17  18 19 1a 1b 1c 1d 1e 1f
00000020: 20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f
00000030: 30 31 32 33 34 35 36 37  38 39 3a 3b 3c 3d 3e 3f
00000040: 40 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f
00000050: 50 51 52 53 54 55 56 57  58 59 5a 5b 5c 5d 5e 5f
00000060: 60 61 62 63
sh>
sh>fal erase easyflash 0 100
part page size: 0x1000, erase size:0x1000, size:0x80000
erase failed 4096/100
sh>fal read easyflash 0 100
part page size: 0x1000, erase size:0x1000, size:0x80000
read offset:0x0 count=100/100
read success
00000000: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000010: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000020: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000030: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000040: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000050: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000060: ff ff ff ff
sh>

11.5 注意事项

部分flash芯片有擦除和读写的长度要求,做拓展开发时请注意!

第十二章 TF卡挂载文件系统实验

12.1 简介

本实验将开发板上TF卡槽中的TF卡作为文件系统的存储设备,在TF卡上创建文件系统(格式化卡),并挂载文件系统到OneOS物联网操作系统中,实现对TF卡的文件管理。

12.2 硬件说明

TF卡使用SPI口与处理器相连,硬件连接如图:

TFcard_schematic

各管脚作用如下表:

名称 管脚 作用
NRF_CS PB12 SPI2片选信号
SPI2_MOSI PB15 SPI2数据信号
SPI2_SCK PB13 SPI2时钟信号
SPI2_MISO PB14 SPI2数据信号
NRF_CE PB11 TF卡使能信号

12.3 软件说明

1、在挂载文件系统之前,需要先创建SD卡块存储设备。sd0是基于spi2设备而创建的,创建块设备的代码在drivers/spi_tfcard.c文件中。msd_init函数会在spi_tfcard设备上进行探测,并基于该设备创建名为sd0的块设备,用于文件系统的挂载,代码如下所示:

static int os_hw_spi_tfcard(void)
{
    os_hw_spi_device_attach(BSP_SDCARD_SPI_DEV, "spi_tfcard", BSP_SDCARD_SPI_CS_PIN);
    return msd_init("sd0", "spi_tfcard");
}
OS_CMPOENT_INIT(os_hw_spi_tfcard);

2、可通过以下示例代码将块设备sd0中的文件系统以fatfs文件系统格式挂载到根目录”/“上。

int sdmmc_test( void )
{     
    /* mount the file system from tf card */
    if (vfs_mount("sd0", "/", "fat", 0, 0) == 0)
    {
        os_kprintf("Filesystem initialized!\n");
    }
    else
    {
        os_kprintf("Failed to initialize filesystem!\n");
    }

    return 0;
}
SH_CMD_EXPORT(sdmmc_test, sdmmc_test, "sdmmc_test");

12.4 编译运行

12.4.1 STM32CubeMX配置

根据硬件设计原理图可知,SPI2需要配置为全双工模式,如下图所示:

SPI2的的参数配置参考SPI1,一般保持默认即可。

12.4.2 OnsOS-Cube配置

1、Drivers→ SPI路径下配置TF卡SPI2接口与相关设置。

2、Drivers→ SPI→ Enable SDCARD (SPI)路径下,配置TF卡的SPI总线名称与片选信号。

3、进入组件配置界面,在虚拟文件系统中使能fat,并进行相关属性配置,如分卷大小为4096。

FAT相关配置:

12.4.2 scons编译

完成OnsOS-Cube配置后,使用scons指令:scons --ide=mdk5编译生成keil工程。

12.4.3 运行

使用keil5打开工程project.uvprojx ,编译下载程序。运行程序后,在控制台中,输入devcie指令。

sh />device
device                  type         ref count
--------------- -------------------- ----------
sd0             Block Device         0
spi_tfcard      SPI Device           0
cortexm_systick ClockEvent Device    1
spi3            SPI Bus              0
spi2            SPI Bus              0
spi1            SPI Bus              0
uart3           Character Device     2
uart2           Character Device     0
uart1           Character Device     0
uart4           Character Device     0
cortexm_dwt     ClockSource Device   1
pin_0           Miscellaneous Device 0
sh />

2、输入sdmmc_test测试指令,系统打印文件系统初始化完成,输入ls指令,可查看当前sd卡中的内容。

sh />sdmmc_test
Filesystem initialized!
sh />ls
Directory /:
System Volume Information<DIR>
3.wav               43159596
fei.wav             14018886
lin.wav             52616064
liu.wav             37643974
test.wav            321324
test.wv             0
test1.wav           231468
test2.wav           231468
zhang.wav           38382556
zhou.wav            50883344
MUSIC               <DIR>
RECORDER            <DIR>
1.wav               52616064
2.wav               43159596
sh />

12.5 注意事项

FAL组件会自动勾选上。

results matching ""

    No results matching ""

    返回顶部