├── .gitignore ├── rtc_sample.c ├── SConscript ├── adc_vol_sample.c ├── README_ZH.md ├── pin_beep_sample.c ├── pwm_led_sample.c ├── led_blink_sample.c ├── spi_w25q_sample.c ├── iwdg_sample.c ├── README.md ├── hwtimer_sample.c ├── uart_sample.c ├── drv_sample.c ├── uart_dma_sample.c ├── sd_sample.c ├── i2c_aht10_sample.c ├── can_sample.c └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /rtc_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-11-30 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 RTC 设备使用例程 12 | * 例程导出了 rtc_sample 命令到控制终端 13 | * 命令调用格式:rtc_sample 14 | * 程序功能:设置RTC设备的日期和时间,延时一段时间后获取当前时间并打印显示。 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | static int rtc_sample(int argc, char *argv[]) 21 | { 22 | rt_err_t ret = RT_EOK; 23 | time_t now; 24 | 25 | /* 设置日期 */ 26 | ret = set_date(2018, 12, 3); 27 | if (ret != RT_EOK) 28 | { 29 | rt_kprintf("set RTC date failed\n"); 30 | return ret; 31 | } 32 | 33 | /* 设置时间 */ 34 | ret = set_time(11, 15, 50); 35 | if (ret != RT_EOK) 36 | { 37 | rt_kprintf("set RTC time failed\n"); 38 | return ret; 39 | } 40 | 41 | /* 延时3秒 */ 42 | rt_thread_mdelay(3000); 43 | 44 | /* 获取时间 */ 45 | now = time(RT_NULL); 46 | rt_kprintf("%s\n", ctime(&now)); 47 | 48 | return ret; 49 | } 50 | /* 导出到 msh 命令列表中 */ 51 | MSH_CMD_EXPORT(rtc_sample, rtc sample); 52 | -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | from building import * 2 | 3 | src = [] 4 | cwd = GetCurrentDir() 5 | include_path = [cwd] 6 | 7 | if GetDepend('PERIPHERAL_SAMPLES_USING_ADC'): 8 | src += ['adc_vol_sample.c'] 9 | 10 | if GetDepend('PERIPHERAL_SAMPLES_USING_CAN'): 11 | src += ['can_sample.c'] 12 | 13 | if GetDepend('PERIPHERAL_SAMPLES_USING_HWTIMER'): 14 | src += ['hwtimer_sample.c'] 15 | 16 | if GetDepend('PERIPHERAL_SAMPLES_USING_I2C'): 17 | src += ['i2c_aht10_sample.c'] 18 | 19 | if GetDepend('PERIPHERAL_SAMPLES_USING_IWDG'): 20 | src += ['iwdg_sample.c'] 21 | 22 | if GetDepend('PERIPHERAL_SAMPLES_USING_LED_BLINK'): 23 | src += ['led_blink_sample.c'] 24 | 25 | if GetDepend('PERIPHERAL_SAMPLES_USING_PIN'): 26 | src += Glob('pin_beep_sample.c') 27 | 28 | if GetDepend('PERIPHERAL_SAMPLES_USING_PWM'): 29 | src += ['pwm_led_sample.c'] 30 | 31 | if GetDepend('PERIPHERAL_SAMPLES_USING_RTC'): 32 | src += ['rtc_sample.c'] 33 | 34 | if GetDepend('PERIPHERAL_SAMPLES_USING_SD'): 35 | src += ['sd_sample.c'] 36 | 37 | if GetDepend('PERIPHERAL_SAMPLES_USING_SERIAL'): 38 | src += Glob('uart_sample.c') 39 | 40 | if GetDepend('PERIPHERAL_SAMPLES_USING_SERIAL_DMA'): 41 | src += Glob('uart_dma_sample.c') 42 | 43 | if GetDepend('PERIPHERAL_SAMPLES_USING_SPI'): 44 | src += Glob('spi_w25q_sample.c') 45 | 46 | if GetDepend('PERIPHERAL_SAMPLES_USING_DRV'): 47 | src += Glob('drv_sample.c') 48 | 49 | group = DefineGroup('peripheral-samples', src, depend = ['PKG_USING_PERIPHERAL_SAMPLES'], CPPPATH = include_path) 50 | 51 | Return('group') 52 | -------------------------------------------------------------------------------- /adc_vol_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-11-29 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单: ADC 设备使用例程 12 | * 例程导出了 adc_sample 命令到控制终端 13 | * 命令调用格式:adc_sample 14 | * 程序功能:通过 ADC 设备采样电压值并转换为数值。 15 | * 示例代码参考电压为3.3V,转换位数为12位。 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define ADC_DEV_NAME "adc1" /* ADC 设备名称 */ 22 | #define ADC_DEV_CHANNEL 5 /* ADC 通道 */ 23 | #define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/ 24 | #define CONVERT_BITS (1 << 12) /* 转换位数为12位 */ 25 | 26 | static int adc_vol_sample(int argc, char *argv[]) 27 | { 28 | rt_adc_device_t adc_dev; 29 | rt_uint32_t value, vol; 30 | rt_err_t ret = RT_EOK; 31 | 32 | /* 查找设备 */ 33 | adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME); 34 | if (adc_dev == RT_NULL) 35 | { 36 | rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME); 37 | return RT_ERROR; 38 | } 39 | 40 | /* 使能设备 */ 41 | ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL); 42 | 43 | /* 读取采样值 */ 44 | value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL); 45 | rt_kprintf("the value is :%d \n", value); 46 | 47 | /* 转换为对应电压值 */ 48 | vol = value * REFER_VOLTAGE / CONVERT_BITS; 49 | rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100); 50 | 51 | /* 关闭通道 */ 52 | ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL); 53 | 54 | return ret; 55 | } 56 | /* 导出到 msh 命令列表中 */ 57 | MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample); 58 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | # peripheral samples package 2 | 3 | 中文页 | [English](README.md) 4 | 5 | ## 1、介绍 6 | 7 | 这个软件包包含一些外设设备操作的例程。 8 | 9 | ### 1.1 例程说明 10 | 11 | | 文件 | 说明 | 12 | | ---------------- | ------------------------------- | 13 | | adc_vol_sample.c | 使用 ADC 设备转换电压数据 | 14 | | hwtimer_sample.c | 使用 硬件定时器定时 | 15 | | i2c_aht10_sample.c | 使用 i2c 设备获取 aht10 温湿度传感器数据 | 16 | | iwdg_sample.c | 看门狗设备使用示例 | 17 | | led_blink_sample.c | 使用 pin 设备控制 LED 闪烁 | 18 | | pin_beep_sample.c | 使用 pin 设备控制蜂鸣器 | 19 | | pwm_led_sample.c | 使用 pwm 设备控制 LED 的亮度 | 20 | | rtc_sample.c | 使用 rtc 设备设置年月日时分秒信息 | 21 | | sd_sample.c | 块设备 SD 卡使用示例 | 22 | | spi_w25q_sample.c | 使用 spi 设备读取 W25Q ID | 23 | | uart_sample.c | 使用 serial 设备中断接收及轮询发送模式收发数据 | 24 | | uart_dma_sample.c | 使用 serial 设备 DMA 接收及轮询发送模式收发数据 | 25 | 26 | ### 1.2 许可证 27 | 28 | peripheral samples package 遵循 Apache license v2.0 许可,详见 `LICENSE` 文件。 29 | 30 | ### 1.3 依赖 31 | 32 | 依赖设备管理模块提供的设备驱动。 33 | 34 | ## 2、如何打开 peripheral samples package 35 | 36 | 使用 peripheral samples package 需要在 RT-Thread 的包管理器中选择它,具体路径如下: 37 | 38 | ``` 39 | RT-Thread online packages 40 | miscellaneous packages ---> 41 | samples: kernel and components samples ---> 42 | a peripheral_samples package for rt-thread ---> 43 | ``` 44 | 45 | 然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。 46 | 47 | ## 3、使用 peripheral samples package 48 | 49 | 在打开 peripheral samples package 后,当进行 BSP 编译时,选择的软件包相关源代码会被加入到 BSP 工程中进行编译。 50 | 51 | ## 4、注意事项 52 | 53 | 暂无。 54 | 55 | ## 5、联系方式 & 感谢 56 | 57 | * 维护:[misonyo](https://github.com/misonyo) 58 | * 主页:https://github.com/RT-Thread-packages/peripheral-sample 59 | -------------------------------------------------------------------------------- /pin_beep_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-08-15 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 PIN 设备使用例程 12 | * 例程导出了 pin_beep_sample 命令到控制终端 13 | * 命令调用格式:pin_beep_sample 14 | * 程序功能:通过按键控制蜂鸣器对应引脚的电平状态控制蜂鸣器 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | /* 引脚编号,通过查看驱动文件drv_gpio.c确定 */ 21 | #ifndef BEEP_PIN_NUM 22 | #define BEEP_PIN_NUM 37 /* PB2 */ 23 | #endif 24 | #ifndef KEY0_PIN_NUM 25 | #define KEY0_PIN_NUM 57 /* PD10 */ 26 | #endif 27 | #ifndef KEY1_PIN_NUM 28 | #define KEY1_PIN_NUM 56 /* PD9 */ 29 | #endif 30 | 31 | void beep_on(void *args) 32 | { 33 | rt_kprintf("turn on beep!\n"); 34 | 35 | rt_pin_write(BEEP_PIN_NUM, PIN_HIGH); 36 | } 37 | 38 | void beep_off(void *args) 39 | { 40 | rt_kprintf("turn off beep!\n"); 41 | 42 | rt_pin_write(BEEP_PIN_NUM, PIN_LOW); 43 | } 44 | 45 | static void pin_beep_sample(void) 46 | { 47 | /* 蜂鸣器引脚为输出模式 */ 48 | rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT); 49 | /* 默认低电平 */ 50 | rt_pin_write(BEEP_PIN_NUM, PIN_LOW); 51 | 52 | /* 按键0引脚为输入模式 */ 53 | rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP); 54 | /* 绑定中断,下降沿模式,回调函数名为beep_on */ 55 | rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL); 56 | /* 使能中断 */ 57 | rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE); 58 | 59 | /* 按键1引脚为输入模式 */ 60 | rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP); 61 | /* 绑定中断,下降沿模式,回调函数名为beep_off */ 62 | rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL); 63 | /* 使能中断 */ 64 | rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE); 65 | } 66 | /* 导出到 msh 命令列表中 */ 67 | MSH_CMD_EXPORT(pin_beep_sample, pin beep sample); 68 | -------------------------------------------------------------------------------- /pwm_led_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-11-25 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 PWM 设备使用例程 12 | * 例程导出了 pwm_led_sample 命令到控制终端 13 | * 命令调用格式:pwm_led_sample 14 | * 程序功能:通过 PWM 设备控制 LED 灯的亮度,可以看到LED不停的由暗变到亮,然后又从亮变到暗。 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define PWM_DEV_NAME "pwm3" /* PWM设备名称 */ 21 | #define PWM_DEV_CHANNEL 4 /* PWM通道 */ 22 | 23 | struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */ 24 | 25 | static int pwm_led_sample(int argc, char *argv[]) 26 | { 27 | rt_uint32_t period, pulse, dir; 28 | 29 | period = 500000; /* 周期为0.5ms,单位为纳秒ns */ 30 | dir = 1; /* PWM脉冲宽度值的增减方向 */ 31 | pulse = 0; /* PWM脉冲宽度值,单位为纳秒ns */ 32 | 33 | /* 查找设备 */ 34 | pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME); 35 | if (pwm_dev == RT_NULL) 36 | { 37 | rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME); 38 | return RT_ERROR; 39 | } 40 | 41 | /* 设置PWM周期和脉冲宽度默认值 */ 42 | rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse); 43 | /* 使能设备 */ 44 | rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL); 45 | 46 | while (1) 47 | { 48 | rt_thread_mdelay(50); 49 | if (dir) 50 | { 51 | pulse += 5000; /* 从0值开始每次增加5000ns */ 52 | } 53 | else 54 | { 55 | pulse -= 5000; /* 从最大值开始每次减少5000ns */ 56 | } 57 | if (pulse >= period) 58 | { 59 | dir = 0; 60 | } 61 | if (0 == pulse) 62 | { 63 | dir = 1; 64 | } 65 | 66 | /* 设置PWM周期和脉冲宽度 */ 67 | rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse); 68 | } 69 | } 70 | /* 导出到 msh 命令列表中 */ 71 | MSH_CMD_EXPORT(pwm_led_sample, pwm sample); 72 | -------------------------------------------------------------------------------- /led_blink_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-09-25 misonyo first edition. 9 | */ 10 | /* 11 | * 程序清单:这是一个通过PIN脚控制LED亮灭的使用例程 12 | * 例程导出了 led_sample 命令到控制终端 13 | * 命令调用格式:led_sample 41 14 | * 命令解释:命令第二个参数是要使用的PIN脚编号,为空则使用例程默认的引脚编号。 15 | * 程序功能:程序创建一个led线程,线程每隔1000ms改变PIN脚状态,达到控制led灯 16 | * 亮灭的效果。 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | /* PIN脚编号,查看驱动文件drv_gpio.c确定 */ 24 | #define LED_PIN_NUM 41 25 | static int pin_num; 26 | 27 | static void led_entry(void *parameter) 28 | { 29 | int count = 0; 30 | /* 设置PIN脚模式为输出 */ 31 | rt_pin_mode(pin_num, PIN_MODE_OUTPUT); 32 | 33 | while (1) 34 | { 35 | count++; 36 | rt_kprintf("thread run count : %d\r\n", count); 37 | /* 拉低PIN脚 */ 38 | rt_pin_write(pin_num, PIN_LOW); 39 | rt_kprintf("led on!\r\n"); 40 | /* 延时1000ms */ 41 | rt_thread_mdelay(1000); 42 | 43 | /* 拉高PIN脚 */ 44 | rt_pin_write(pin_num, PIN_HIGH); 45 | rt_kprintf("led off!\r\n"); 46 | rt_thread_mdelay(1000); 47 | } 48 | } 49 | 50 | static int led_sample(int argc, char *argv[]) 51 | { 52 | rt_thread_t tid; 53 | rt_err_t ret = RT_EOK; 54 | 55 | /* 判断命令行参数是否给定了PIN脚编号 */ 56 | if (argc == 2) 57 | { 58 | pin_num = atoi(argv[1]); 59 | } 60 | else 61 | { 62 | pin_num = LED_PIN_NUM; 63 | } 64 | 65 | tid = rt_thread_create("led", 66 | led_entry, 67 | RT_NULL, 68 | 512, 69 | RT_THREAD_PRIORITY_MAX / 3, 70 | 20); 71 | if (tid != RT_NULL) 72 | { 73 | rt_thread_startup(tid); 74 | } 75 | else 76 | { 77 | ret = RT_ERROR; 78 | } 79 | 80 | return ret; 81 | } 82 | /* 导出到 msh 命令列表中 */ 83 | MSH_CMD_EXPORT(led_sample, led sample); 84 | -------------------------------------------------------------------------------- /spi_w25q_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-08-15 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 SPI 设备使用例程 12 | * 例程导出了 spi_w25q_sample 命令到控制终端 13 | * 命令调用格式:spi_w25q_sample spi10 14 | * 命令解释:命令第二个参数是要使用的SPI设备名称,为空则使用默认的SPI设备 15 | * 程序功能:通过SPI设备读取 w25q 的 ID 数据 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define W25Q_SPI_DEVICE_NAME "qspi10" 22 | 23 | static void spi_w25q_sample(int argc, char *argv[]) 24 | { 25 | struct rt_spi_device *spi_dev_w25q; 26 | char name[RT_NAME_MAX]; 27 | rt_uint8_t w25x_read_id = 0x90; 28 | rt_uint8_t id[5] = {0}; 29 | 30 | if (argc == 2) 31 | { 32 | rt_strncpy(name, argv[1], RT_NAME_MAX); 33 | } 34 | else 35 | { 36 | rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX); 37 | } 38 | 39 | /* 查找 spi 设备获取设备句柄 */ 40 | spi_dev_w25q = (struct rt_spi_device *)rt_device_find(name); 41 | if (!spi_dev_w25q) 42 | { 43 | rt_kprintf("spi sample run failed! can't find %s device!\n", name); 44 | } 45 | else 46 | { 47 | /* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */ 48 | rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5); 49 | rt_kprintf("use rt_spi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]); 50 | 51 | /* 方式2:使用 rt_spi_transfer_message()发送命令读取ID */ 52 | struct rt_spi_message msg1, msg2; 53 | 54 | msg1.send_buf = &w25x_read_id; 55 | msg1.recv_buf = RT_NULL; 56 | msg1.length = 1; 57 | msg1.cs_take = 1; 58 | msg1.cs_release = 0; 59 | msg1.next = &msg2; 60 | 61 | msg2.send_buf = RT_NULL; 62 | msg2.recv_buf = id; 63 | msg2.length = 5; 64 | msg2.cs_take = 0; 65 | msg2.cs_release = 1; 66 | msg2.next = RT_NULL; 67 | 68 | rt_spi_transfer_message(spi_dev_w25q, &msg1); 69 | rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", id[3], id[4]); 70 | 71 | } 72 | } 73 | /* 导出到 msh 命令列表中 */ 74 | MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample); 75 | -------------------------------------------------------------------------------- /iwdg_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-09-25 misonyo first edition. 9 | */ 10 | /* 11 | * 程序清单:这是一个独立看门狗设备使用例程 12 | * 例程导出了 iwdg_sample 命令到控制终端 13 | * 命令调用格式:iwdg_sample iwg 14 | * 命令解释:命令第二个参数是要使用的看门狗设备名称,为空则使用例程默认的看门狗设备。 15 | * 程序功能:程序通过设备名称查找看门狗设备,然后初始化设备并设置看门狗设备溢出时间。 16 | * 然后设置空闲线程回调函数,在回调函数里会喂狗。 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #define IWDG_DEVICE_NAME "wdt" /* 看门狗设备名称 */ 23 | 24 | static rt_device_t wdg_dev; /* 看门狗设备句柄 */ 25 | 26 | static void idle_hook(void) 27 | { 28 | /* 在空闲线程的回调函数里喂狗 */ 29 | rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL); 30 | rt_kprintf("feed the dog!\n "); 31 | } 32 | 33 | static int iwdg_sample(int argc, char *argv[]) 34 | { 35 | rt_err_t ret = RT_EOK; 36 | rt_uint32_t timeout = 10; /* 溢出时间 10 秒 */ 37 | char device_name[RT_NAME_MAX]; 38 | 39 | /* 判断命令行参数是否给定了设备名称 */ 40 | if (argc == 2) 41 | { 42 | rt_strncpy(device_name, argv[1], RT_NAME_MAX); 43 | } 44 | else 45 | { 46 | rt_strncpy(device_name, IWDG_DEVICE_NAME, RT_NAME_MAX); 47 | } 48 | /* 根据设备名称查找看门狗设备,获取设备句柄 */ 49 | wdg_dev = rt_device_find(device_name); 50 | if (!wdg_dev) 51 | { 52 | rt_kprintf("find %s failed!\n", device_name); 53 | return -RT_ERROR; 54 | } 55 | /* 初始化设备 */ 56 | ret = rt_device_init(wdg_dev); 57 | if (ret != RT_EOK) 58 | { 59 | rt_kprintf("initialize %s failed!\n", device_name); 60 | return -RT_ERROR; 61 | } 62 | /* 设置看门狗溢出时间 */ 63 | ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); 64 | if (ret != RT_EOK) 65 | { 66 | rt_kprintf("set %s timeout failed!\n", device_name); 67 | return -RT_ERROR; 68 | } 69 | ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); 70 | if (ret != RT_EOK) 71 | { 72 | rt_kprintf("start %s failed!\n", device_name); 73 | return -RT_ERROR; 74 | } 75 | /* 设置空闲线程回调函数 */ 76 | rt_thread_idle_sethook(idle_hook); 77 | 78 | return ret; 79 | } 80 | /* 导出到 msh 命令列表中 */ 81 | MSH_CMD_EXPORT(iwdg_sample, iwdg sample); 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # peripheral samples package 2 | 3 | [中文页](README_ZH.md) | English 4 | 5 | ## 1. Introduction 6 | 7 | This package contains some routines for the operation of peripheral devices. 8 | 9 | ### 1.1 Example description 10 | 11 | | File | Description | 12 | | ---------------- | ------------------------------- | 13 | | adc_vol_sample.c | Use ADC device to convert voltage data | 14 | | hwtimer_sample.c | Use hardware timer timing | 15 | | i2c_aht10_sample.c | Use i2c device to obtain aht10 temperature and humidity sensor data | 16 | | iwdg_sample.c | Watchdog device usage example | 17 | | led_blink_sample.c | Use pin device to control LED blinking | 18 | | pin_beep_sample.c | Use pin device to control buzzer | 19 | | pwm_led_sample.c | Use pwm device to control LED brightness | 20 | | rtc_sample.c | Use rtc device to set year, month, day, hour, minute and second information | 21 | | sd_sample.c | Block device SD card usage example | 22 | | spi_w25q_sample.c | Use spi device to read W25Q ID | 23 | | uart_sample.c | Send and receive data using serial device interrupt receiving and polling sending mode | 24 | | uart_dma_sample.c | Use serial device DMA reception and polling transmission mode to send and receive data | 25 | 26 | ### 1.2 License 27 | 28 | The peripheral samples package complies with the Apache license v2.0, see the `LICENSE` file for details. 29 | 30 | ### 1.3 Dependency 31 | 32 | Depend on the device driver provided by the device management module. 33 | 34 | ## 2. How to open the peripheral samples package 35 | 36 | To use the peripheral samples package, you need to select it in the RT-Thread package manager. The specific path is as follows: 37 | 38 | ``` 39 | RT-Thread online packages 40 | miscellaneous packages ---> 41 | samples: kernel and components samples ---> 42 | a peripheral_samples package for rt-thread ---> 43 | ``` 44 | 45 | Then let the RT-Thread package manager automatically update, or use the `pkgs --update` command to update the package to the BSP. 46 | 47 | ## 3. Use peripheral samples package 48 | 49 | After opening the peripheral samples package, when the BSP is compiled, the relevant source code of the selected software package will be added to the BSP project for compilation. 50 | 51 | ## 4. Matters needing attention 52 | 53 | Nothing. 54 | 55 | ## 5. Contact & Thanks 56 | 57 | * Maintenance: [misonyo](https://github.com/misonyo) 58 | * Homepage: https://github.com/RT-Thread-packages/peripheral-sample 59 | -------------------------------------------------------------------------------- /hwtimer_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-11-30 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 hwtimer 设备使用例程 12 | * 例程导出了 hwtimer_sample 命令到控制终端 13 | * 命令调用格式:hwtimer_sample 14 | * 程序功能:硬件定时器超时回调函数周期性的打印当前tick值,2次tick值之差换算为时间等同于定时时间值。 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define HWTIMER_DEV_NAME "timer0" /* 定时器名称 */ 21 | 22 | /* 定时器超时回调函数 */ 23 | static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) 24 | { 25 | rt_kprintf("tick is :%d !\n", rt_tick_get()); 26 | 27 | return 0; 28 | } 29 | 30 | static int hwtimer_sample(int argc, char *argv[]) 31 | { 32 | rt_err_t ret = RT_EOK; 33 | rt_hwtimerval_t timeout_s; /* 定时器超时值 */ 34 | rt_device_t hw_dev = RT_NULL; /* 定时器设备句柄 */ 35 | rt_hwtimer_mode_t mode; /* 定时器模式 */ 36 | 37 | /* 查找定时器设备 */ 38 | hw_dev = rt_device_find(HWTIMER_DEV_NAME); 39 | if (hw_dev == RT_NULL) 40 | { 41 | rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME); 42 | return RT_ERROR; 43 | } 44 | 45 | /* 以读写方式打开设备 */ 46 | ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); 47 | if (ret != RT_EOK) 48 | { 49 | rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME); 50 | return ret; 51 | } 52 | 53 | /* 设置超时回调函数 */ 54 | rt_device_set_rx_indicate(hw_dev, timeout_cb); 55 | 56 | /* 设置模式为周期性定时器 */ 57 | mode = HWTIMER_MODE_PERIOD; 58 | ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode); 59 | if (ret != RT_EOK) 60 | { 61 | rt_kprintf("set mode failed! ret is :%d\n", ret); 62 | return ret; 63 | } 64 | 65 | /* 设置定时器超时值为5s并启动定时器 */ 66 | timeout_s.sec = 5; /* 秒 */ 67 | timeout_s.usec = 0; /* 微秒 */ 68 | 69 | if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s)) 70 | { 71 | rt_kprintf("set timeout value failed\n"); 72 | return RT_ERROR; 73 | } 74 | 75 | /* 延时3500ms */ 76 | rt_thread_mdelay(3500); 77 | 78 | /* 读取定时器当前值 */ 79 | rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s)); 80 | rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec); 81 | 82 | return ret; 83 | } 84 | /* 导出到 msh 命令列表中 */ 85 | MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample); 86 | -------------------------------------------------------------------------------- /uart_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-08-15 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 串口 设备使用例程 12 | * 例程导出了 uart_sample 命令到控制终端 13 | * 命令调用格式:uart_sample uart2 14 | * 命令解释:命令第二个参数是要使用的串口设备名称,为空则使用默认的串口设备 15 | * 程序功能:通过串口输出字符串"hello RT-Thread!",然后错位输出输入的字符 16 | */ 17 | 18 | #include 19 | 20 | #define SAMPLE_UART_NAME "uart2" /* 串口设备名称 */ 21 | 22 | /* 用于接收消息的信号量 */ 23 | static struct rt_semaphore rx_sem; 24 | static rt_device_t serial; 25 | 26 | /* 接收数据回调函数 */ 27 | static rt_err_t uart_input(rt_device_t dev, rt_size_t size) 28 | { 29 | /* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */ 30 | rt_sem_release(&rx_sem); 31 | 32 | return RT_EOK; 33 | } 34 | 35 | static void serial_thread_entry(void *parameter) 36 | { 37 | char ch; 38 | 39 | while (1) 40 | { 41 | /* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */ 42 | while (rt_device_read(serial, -1, &ch, 1) != 1) 43 | { 44 | /* 阻塞等待接收信号量,等到信号量后再次读取数据 */ 45 | rt_sem_take(&rx_sem, RT_WAITING_FOREVER); 46 | } 47 | /* 读取到的数据通过串口错位输出 */ 48 | ch = ch + 1; 49 | rt_device_write(serial, 0, &ch, 1); 50 | } 51 | } 52 | 53 | static int uart_sample(int argc, char *argv[]) 54 | { 55 | rt_err_t ret = RT_EOK; 56 | char uart_name[RT_NAME_MAX]; 57 | char str[] = "hello RT-Thread!\r\n"; 58 | 59 | if (argc == 2) 60 | { 61 | rt_strncpy(uart_name, argv[1], RT_NAME_MAX); 62 | } 63 | else 64 | { 65 | rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX); 66 | } 67 | 68 | /* 查找串口设备 */ 69 | serial = rt_device_find(uart_name); 70 | if (!serial) 71 | { 72 | rt_kprintf("find %s failed!\n", uart_name); 73 | return RT_ERROR; 74 | } 75 | 76 | /* 初始化信号量 */ 77 | rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); 78 | /* 以中断接收及轮询发送方式打开串口设备 */ 79 | rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); 80 | /* 设置接收回调函数 */ 81 | rt_device_set_rx_indicate(serial, uart_input); 82 | /* 发送字符串 */ 83 | rt_device_write(serial, 0, str, (sizeof(str) - 1)); 84 | 85 | /* 创建 serial 线程 */ 86 | rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10); 87 | /* 创建成功则启动线程 */ 88 | if (thread != RT_NULL) 89 | { 90 | rt_thread_startup(thread); 91 | } 92 | else 93 | { 94 | ret = RT_ERROR; 95 | } 96 | 97 | return ret; 98 | } 99 | /* 导出到 msh 命令列表中 */ 100 | MSH_CMD_EXPORT(uart_sample, uart device sample); 101 | -------------------------------------------------------------------------------- /drv_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2024, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2024-07-23 Wangyuqiang first version 9 | */ 10 | /* 11 | * 程序清单:这是一个 模拟test字符设备驱动使用例程 12 | * 例程导出了 drv_sample 命令到控制终端 13 | * 命令调用格式:drv_sample 14 | * 程序功能:模拟一个字符设备驱动,使开发者无需对接驱动框架即可体验RT-Thread设备驱动。 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | static rt_err_t drv_test_init(rt_device_t dev) 21 | { 22 | rt_kprintf("Test drv init!\n"); 23 | return RT_EOK; 24 | } 25 | 26 | static rt_err_t drv_test_open(rt_device_t dev, rt_uint16_t oflag) 27 | { 28 | rt_kprintf("Test drv open flag = %d.\n", oflag); 29 | return RT_EOK; 30 | } 31 | 32 | static rt_err_t drv_test_close(rt_device_t dev) 33 | { 34 | rt_kprintf("Test drv close!\n"); 35 | return RT_EOK; 36 | } 37 | 38 | static rt_ssize_t drv_test_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) 39 | { 40 | rt_kprintf("Test drv read pos = %d, size = %d.\n", pos, size); 41 | return size; 42 | } 43 | 44 | static rt_ssize_t drv_test_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) 45 | { 46 | rt_kprintf("Test drv write pos = %d, size = %d.\n", pos, size); 47 | return size; 48 | } 49 | 50 | static rt_err_t drv_test_control(rt_device_t dev, int cmd, void *args) 51 | { 52 | rt_kprintf("Test drv control cmd = %d.\n", cmd); 53 | return RT_EOK; 54 | } 55 | 56 | int rt_drv_test_init(void) 57 | { 58 | rt_device_t test_dev = rt_device_create(RT_Device_Class_Char, 0); 59 | if(!test_dev) 60 | { 61 | rt_kprintf("Test drv create failed!\n"); 62 | return -RT_ERROR; 63 | } 64 | 65 | test_dev->init = drv_test_init; 66 | test_dev->open = drv_test_open; 67 | test_dev->close = drv_test_close; 68 | test_dev->read = drv_test_read; 69 | test_dev->write = drv_test_write; 70 | test_dev->control = drv_test_control; 71 | 72 | if(rt_device_register(test_dev, "test_drv", RT_DEVICE_FLAG_RDWR) != RT_EOK) 73 | { 74 | rt_kprintf("Test drv register failed!\n"); 75 | return -RT_ERROR; 76 | } 77 | 78 | return RT_EOK; 79 | } 80 | INIT_BOARD_EXPORT(rt_drv_test_init); 81 | 82 | static int drv_sample(void) 83 | { 84 | rt_device_t test_dev = rt_device_find("test_drv"); 85 | if(test_dev == RT_NULL) 86 | { 87 | rt_kprintf("Can not find test drv!\n"); 88 | return -RT_ERROR; 89 | } 90 | 91 | rt_device_open(test_dev, RT_DEVICE_OFLAG_RDWR); 92 | rt_device_control(test_dev, RT_DEVICE_CTRL_CONFIG, RT_NULL); 93 | rt_device_write(test_dev, 100, RT_NULL, 1024); 94 | rt_device_read(test_dev, 20, RT_NULL, 128); 95 | 96 | rt_device_close(test_dev); 97 | 98 | return RT_EOK; 99 | } 100 | MSH_CMD_EXPORT(drv_sample, enable test drv sample); 101 | -------------------------------------------------------------------------------- /uart_dma_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-04-16 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个串口设备 DMA 接收使用例程 12 | * 例程导出了 uart_dma_sample 命令到控制终端 13 | * 命令调用格式:uart_dma_sample uart3 14 | * 命令解释:命令第二个参数是要使用的串口设备名称,为空则使用默认的串口设备 15 | * 程序功能:通过串口输出字符串"hello RT-Thread!",并通过串口输出接收到的数据,然后打印接收到的数据。 16 | */ 17 | 18 | #include 19 | 20 | #define SAMPLE_UART_NAME "uart3" /* 串口设备名称 */ 21 | 22 | /* 串口接收消息结构*/ 23 | struct rx_msg 24 | { 25 | rt_device_t dev; 26 | rt_size_t size; 27 | }; 28 | /* 串口设备句柄 */ 29 | static rt_device_t serial; 30 | /* 消息队列控制块 */ 31 | static struct rt_messagequeue rx_mq; 32 | 33 | /* 接收数据回调函数 */ 34 | static rt_err_t uart_input(rt_device_t dev, rt_size_t size) 35 | { 36 | struct rx_msg msg; 37 | rt_err_t result; 38 | msg.dev = dev; 39 | msg.size = size; 40 | 41 | result = rt_mq_send(&rx_mq, &msg, sizeof(msg)); 42 | if ( result == -RT_EFULL) 43 | { 44 | /* 消息队列满 */ 45 | rt_kprintf("message queue full!\n"); 46 | } 47 | return result; 48 | } 49 | 50 | static void serial_thread_entry(void *parameter) 51 | { 52 | struct rx_msg msg; 53 | rt_err_t result; 54 | rt_uint32_t rx_length; 55 | static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1]; 56 | 57 | while (1) 58 | { 59 | rt_memset(&msg, 0, sizeof(msg)); 60 | /* 从消息队列中读取消息*/ 61 | result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER); 62 | if (result == RT_EOK) 63 | { 64 | /* 从串口读取数据*/ 65 | rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size); 66 | rx_buffer[rx_length] = '\0'; 67 | /* 通过串口设备 serial 输出读取到的消息 */ 68 | rt_device_write(serial, 0, rx_buffer, rx_length); 69 | /* 打印数据 */ 70 | rt_kprintf("%s\n",rx_buffer); 71 | } 72 | } 73 | } 74 | 75 | static int uart_dma_sample(int argc, char *argv[]) 76 | { 77 | rt_err_t ret = RT_EOK; 78 | char uart_name[RT_NAME_MAX]; 79 | static char msg_pool[256]; 80 | char str[] = "hello RT-Thread!\r\n"; 81 | 82 | if (argc == 2) 83 | { 84 | rt_strncpy(uart_name, argv[1], RT_NAME_MAX); 85 | } 86 | else 87 | { 88 | rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX); 89 | } 90 | 91 | /* 查找串口设备 */ 92 | serial = rt_device_find(uart_name); 93 | if (!serial) 94 | { 95 | rt_kprintf("find %s failed!\n", uart_name); 96 | return RT_ERROR; 97 | } 98 | 99 | /* 初始化消息队列 */ 100 | rt_mq_init(&rx_mq, "rx_mq", 101 | msg_pool, /* 存放消息的缓冲区 */ 102 | sizeof(struct rx_msg), /* 一条消息的最大长度 */ 103 | sizeof(msg_pool), /* 存放消息的缓冲区大小 */ 104 | RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */ 105 | 106 | /* 以 DMA 接收及轮询发送方式打开串口设备 */ 107 | rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX); 108 | /* 设置接收回调函数 */ 109 | rt_device_set_rx_indicate(serial, uart_input); 110 | /* 发送字符串 */ 111 | rt_device_write(serial, 0, str, (sizeof(str) - 1)); 112 | 113 | /* 创建 serial 线程 */ 114 | rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10); 115 | /* 创建成功则启动线程 */ 116 | if (thread != RT_NULL) 117 | { 118 | rt_thread_startup(thread); 119 | } 120 | else 121 | { 122 | ret = RT_ERROR; 123 | } 124 | 125 | return ret; 126 | } 127 | /* 导出到 msh 命令列表中 */ 128 | MSH_CMD_EXPORT(uart_dma_sample, uart device dma sample); 129 | -------------------------------------------------------------------------------- /sd_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-09-25 misonyo first edition. 9 | */ 10 | /* 11 | * 程序清单:这是一个SD卡设备的使用例程 12 | * 例程导出了 sd_sample 命令到控制终端 13 | * 命令调用格式:sd_sample sd0 14 | * 命令解释:命令第二个参数是要使用的SD设备的名称,为空则使用例程默认的SD设备。 15 | * 程序功能:程序会产生一个块大小的随机数,然后写入SD卡中,然后在读取这部分写入的数据。 16 | * 对比写入和读出的数据是否一致,一致则表示程序运行正确。 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define SD_DEVICE_NAME "sd0" 24 | 25 | void fill_buffer(rt_uint8_t *buff, rt_uint32_t buff_length) 26 | { 27 | rt_uint32_t index; 28 | /* 往缓冲区填充随机数 */ 29 | for (index = 0; index < buff_length; index++) 30 | { 31 | buff[index] = ((rt_uint8_t)rand()) & 0xff; 32 | } 33 | } 34 | 35 | static int sd_sample(int argc, char *argv[]) 36 | { 37 | rt_err_t ret; 38 | rt_device_t sd_device; 39 | char sd_name[RT_NAME_MAX]; 40 | rt_uint8_t *write_buff, *read_buff; 41 | struct rt_device_blk_geometry geo; 42 | rt_uint8_t block_num; 43 | /* 判断命令行参数是否给定了设备名称 */ 44 | if (argc == 2) 45 | { 46 | rt_strncpy(sd_name, argv[1], RT_NAME_MAX); 47 | } 48 | else 49 | { 50 | rt_strncpy(sd_name, SD_DEVICE_NAME, RT_NAME_MAX); 51 | } 52 | /* 查找设备获取设备句柄 */ 53 | sd_device = rt_device_find(sd_name); 54 | if (sd_device == RT_NULL) 55 | { 56 | rt_kprintf("find device %s failed!\n", sd_name); 57 | return RT_ERROR; 58 | } 59 | /* 打开设备 */ 60 | ret = rt_device_open(sd_device, RT_DEVICE_OFLAG_RDWR); 61 | if (ret != RT_EOK) 62 | { 63 | rt_kprintf("open device %s failed!\n", sd_name); 64 | return ret; 65 | } 66 | 67 | rt_memset(&geo, 0, sizeof(geo)); 68 | /* 获取块设备信息 */ 69 | ret = rt_device_control(sd_device, RT_DEVICE_CTRL_BLK_GETGEOME, &geo); 70 | if (ret != RT_EOK) 71 | { 72 | rt_kprintf("control device %s failed!\n", sd_name); 73 | return ret; 74 | } 75 | rt_kprintf("device information:\n"); 76 | rt_kprintf("sector size : %d byte\n", geo.bytes_per_sector); 77 | rt_kprintf("sector count : %d \n", geo.sector_count); 78 | rt_kprintf("block size : %d byte\n", geo.block_size); 79 | /* 准备读写缓冲区空间,大小为一个块 */ 80 | read_buff = rt_malloc(geo.block_size); 81 | if (read_buff == RT_NULL) 82 | { 83 | rt_kprintf("no memory for read buffer!\n"); 84 | return RT_ERROR; 85 | } 86 | write_buff = rt_malloc(geo.block_size); 87 | if (write_buff == RT_NULL) 88 | { 89 | rt_kprintf("no memory for write buffer!\n"); 90 | rt_free(read_buff); 91 | return RT_ERROR; 92 | } 93 | 94 | /* 填充写数据缓冲区,为写操作做准备 */ 95 | fill_buffer(write_buff, geo.block_size); 96 | 97 | /* 把写数据缓冲的数据写入SD卡中,大小为一个块,size参数以块为单位 */ 98 | block_num = rt_device_write(sd_device, 0, write_buff, 1); 99 | if (1 != block_num) 100 | { 101 | rt_kprintf("write device %s failed!\n", sd_name); 102 | } 103 | 104 | /* 从SD卡中读出数据,并保存在读数据缓冲区中 */ 105 | block_num = rt_device_read(sd_device, 0, read_buff, 1); 106 | if (1 != block_num) 107 | { 108 | rt_kprintf("read %s device failed!\n", sd_name); 109 | } 110 | 111 | /* 比较写数据缓冲区和读数据缓冲区的内容是否完全一致 */ 112 | if (rt_memcmp(write_buff, read_buff, geo.block_size) == 0) 113 | { 114 | rt_kprintf("Block test OK!\n"); 115 | } 116 | else 117 | { 118 | rt_kprintf("Block test Fail!\n"); 119 | } 120 | /* 释放缓冲区空间 */ 121 | rt_free(read_buff); 122 | rt_free(write_buff); 123 | 124 | ret = rt_device_close(sd_device); 125 | if(ret != RT_EOK) 126 | { 127 | rt_kprintf("close device %s failed!\n", sd_name); 128 | return ret; 129 | } 130 | else 131 | { 132 | rt_kprintf("close device %s ok!\n", sd_name); 133 | } 134 | 135 | return RT_EOK; 136 | } 137 | /* 导出到 msh 命令列表中 */ 138 | MSH_CMD_EXPORT(sd_sample, sd device sample); 139 | -------------------------------------------------------------------------------- /i2c_aht10_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-08-15 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 I2C 设备使用例程 12 | * 例程导出了 i2c_aht10_sample 命令到控制终端 13 | * 命令调用格式:i2c_aht10_sample i2c1 14 | * 命令解释:命令第二个参数是要使用的I2C总线设备名称,为空则使用默认的I2C总线设备 15 | * 程序功能:通过 I2C 设备读取温湿度传感器 aht10 的温湿度数据并打印 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define AHT10_I2C_BUS_NAME "i2c2" /* 传感器连接的I2C总线设备名称 */ 22 | #define AHT10_ADDR 0x38 /* 从机地址 */ 23 | #define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令 */ 24 | #define AHT10_NORMAL_CMD 0xA8 /* 一般命令 */ 25 | #define AHT10_GET_DATA 0xAC /* 获取数据命令 */ 26 | 27 | static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */ 28 | static rt_bool_t initialized = RT_FALSE; /* 传感器初始化状态 */ 29 | 30 | /* 写传感器寄存器 */ 31 | static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *data) 32 | { 33 | rt_uint8_t buf[3]; 34 | struct rt_i2c_msg msgs; 35 | 36 | buf[0] = reg; //cmd 37 | buf[1] = data[0]; 38 | buf[2] = data[1]; 39 | 40 | msgs.addr = AHT10_ADDR; 41 | msgs.flags = RT_I2C_WR; 42 | msgs.buf = buf; 43 | msgs.len = 3; 44 | 45 | /* 调用I2C设备接口传输数据 */ 46 | if (rt_i2c_transfer(bus, &msgs, 1) == 1) 47 | { 48 | return RT_EOK; 49 | } 50 | else 51 | { 52 | return -RT_ERROR; 53 | } 54 | } 55 | 56 | /* 读传感器寄存器数据 */ 57 | static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf) 58 | { 59 | struct rt_i2c_msg msgs; 60 | 61 | msgs.addr = AHT10_ADDR; 62 | msgs.flags = RT_I2C_RD; 63 | msgs.buf = buf; 64 | msgs.len = len; 65 | 66 | /* 调用I2C设备接口传输数据 */ 67 | if (rt_i2c_transfer(bus, &msgs, 1) == 1) 68 | { 69 | return RT_EOK; 70 | } 71 | else 72 | { 73 | return -RT_ERROR; 74 | } 75 | } 76 | 77 | static void read_temp_humi(float *cur_temp, float *cur_humi) 78 | { 79 | rt_uint8_t temp[6]; 80 | 81 | write_reg(i2c_bus, AHT10_GET_DATA, 0); /* 发送命令 */ 82 | rt_thread_mdelay(400); 83 | read_regs(i2c_bus, 6, temp); /* 获取传感器数据 */ 84 | 85 | /* 湿度数据转换 */ 86 | *cur_humi = (temp[1] << 12 | temp[2] << 4 | (temp[3] & 0xf0) >> 4) * 100.0 / (1 << 20); 87 | /* 温度数据转换 */ 88 | *cur_temp = ((temp[3] & 0xf) << 16 | temp[4] << 8 | temp[5]) * 200.0 / (1 << 20) - 50; 89 | } 90 | 91 | static void aht10_init(const char *name) 92 | { 93 | rt_uint8_t temp[2] = {0, 0}; 94 | 95 | /* 查找I2C总线设备,获取I2C总线设备句柄 */ 96 | i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); 97 | 98 | if (i2c_bus == RT_NULL) 99 | { 100 | rt_kprintf("can't find %s device!\n", name); 101 | } 102 | else 103 | { 104 | write_reg(i2c_bus, AHT10_NORMAL_CMD, temp); 105 | rt_thread_mdelay(400); 106 | 107 | temp[0] = 0x08; 108 | temp[1] = 0x00; 109 | write_reg(i2c_bus, AHT10_CALIBRATION_CMD, temp); 110 | rt_thread_mdelay(400); 111 | initialized = RT_TRUE; 112 | } 113 | } 114 | 115 | static void i2c_aht10_sample(int argc, char *argv[]) 116 | { 117 | float humidity, temperature; 118 | char name[RT_NAME_MAX]; 119 | 120 | humidity = 0.0; 121 | temperature = 0.0; 122 | 123 | if (argc == 2) 124 | { 125 | rt_strncpy(name, argv[1], RT_NAME_MAX); 126 | } 127 | else 128 | { 129 | rt_strncpy(name, AHT10_I2C_BUS_NAME, RT_NAME_MAX); 130 | } 131 | 132 | if (!initialized) 133 | { 134 | /* 传感器初始化 */ 135 | aht10_init(name); 136 | } 137 | if (initialized) 138 | { 139 | /* 读取温湿度数据 */ 140 | read_temp_humi(&temperature, &humidity); 141 | 142 | rt_kprintf("read aht10 sensor humidity : %d.%d %%\n", (int)humidity, (int)(humidity * 10) % 10); 143 | rt_kprintf("read aht10 sensor temperature: %d.%d \n", (int)temperature, (int)(temperature * 10) % 10); 144 | } 145 | else 146 | { 147 | rt_kprintf("initialize sensor failed!\n"); 148 | } 149 | } 150 | /* 导出到 msh 命令列表中 */ 151 | MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample); 152 | -------------------------------------------------------------------------------- /can_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2022, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-06-25 misonyo first implementation. 9 | */ 10 | /* 11 | * 程序清单:这是一个 CAN 设备使用例程 12 | * 例程导出了 can_sample 命令到控制终端 13 | * 命令调用格式:can_sample can2 14 | * 命令解释:命令第二个参数是要使用的 CAN 设备名称,为空则使用默认的 CAN 设备 15 | * 程序功能:通过 CAN 设备发送一帧,并创建一个线程接收数据然后打印输出。 16 | */ 17 | 18 | #include 19 | #include "rtdevice.h" 20 | 21 | #define CAN_DEV_NAME "can2" /* CAN 设备名称 */ 22 | 23 | static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */ 24 | static rt_device_t can_dev; /* CAN 设备句柄 */ 25 | 26 | /* 接收数据回调函数 */ 27 | static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size) 28 | { 29 | /* CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */ 30 | rt_sem_release(&rx_sem); 31 | 32 | return RT_EOK; 33 | } 34 | 35 | static void can_rx_thread(void *parameter) 36 | { 37 | int i; 38 | rt_err_t res; 39 | struct rt_can_msg rxmsg = {0}; 40 | 41 | /* 设置接收回调函数 */ 42 | rt_device_set_rx_indicate(can_dev, can_rx_call); 43 | 44 | #ifdef RT_CAN_USING_HDR 45 | struct rt_can_filter_item items[5] = 46 | { 47 | RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ff,hdr为-1,设置默认过滤表 */ 48 | RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ff,hdr为-1 */ 49 | RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211,hdr为-1 */ 50 | RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), /* std,match ID:0x486,hdr为-1 */ 51 | {0x555, 0, 0, 0, 0x7ff, 7,} /* std,match ID:0x555,hdr为7,指定设置7号过滤表 */ 52 | }; 53 | struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有5个过滤表 */ 54 | /* 设置硬件过滤表 */ 55 | res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg); 56 | RT_ASSERT(res == RT_EOK); 57 | #endif 58 | 59 | while (1) 60 | { 61 | /* hdr值为-1,表示直接从uselist链表读取数据 */ 62 | #if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 1, 0)) 63 | rxmsg.hdr_index = -1; 64 | #else 65 | rxmsg.hdr = -1; 66 | #endif 67 | /* 阻塞等待接收信号量 */ 68 | rt_sem_take(&rx_sem, RT_WAITING_FOREVER); 69 | /* 从CAN读取一帧数据 */ 70 | rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg)); 71 | /* 打印数据ID及内容 */ 72 | rt_kprintf("ID:%x ", rxmsg.id); 73 | for (i = 0; i < 8; i++) 74 | { 75 | rt_kprintf("%2x ", rxmsg.data[i]); 76 | } 77 | 78 | rt_kprintf("\n"); 79 | } 80 | } 81 | 82 | int can_sample(int argc, char *argv[]) 83 | { 84 | struct rt_can_msg msg = {0}; 85 | rt_err_t res; 86 | rt_size_t size; 87 | rt_thread_t thread; 88 | char can_name[RT_NAME_MAX]; 89 | 90 | if (argc == 2) 91 | { 92 | rt_strncpy(can_name, argv[1], RT_NAME_MAX); 93 | } 94 | else 95 | { 96 | rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX); 97 | } 98 | 99 | can_dev = rt_device_find(can_name); 100 | if (!can_dev) 101 | { 102 | rt_kprintf("find %s failed!\n", can_name); 103 | return RT_ERROR; 104 | } 105 | 106 | /* 初始化CAN接收信号量 */ 107 | rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); 108 | 109 | /* 以中断接收及发送方式打开CAN设备 */ 110 | res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX); 111 | RT_ASSERT(res == RT_EOK); 112 | 113 | thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10); 114 | if (thread != RT_NULL) 115 | { 116 | rt_thread_startup(thread); 117 | } 118 | else 119 | { 120 | rt_kprintf("create can_rx thread failed!\n"); 121 | } 122 | 123 | msg.id = 0x78; /* ID为0x78 */ 124 | msg.ide = RT_CAN_STDID; /* 标准格式 */ 125 | msg.rtr = RT_CAN_DTR; /* 数据帧 */ 126 | msg.len = 8; /* 数据长度为8 */ 127 | /* 待发送的8字节数据 */ 128 | msg.data[0] = 0x00; 129 | msg.data[1] = 0x11; 130 | msg.data[2] = 0x22; 131 | msg.data[3] = 0x33; 132 | msg.data[4] = 0x44; 133 | msg.data[5] = 0x55; 134 | msg.data[6] = 0x66; 135 | msg.data[7] = 0x77; 136 | /* 发送一帧CAN数据 */ 137 | size = rt_device_write(can_dev, 0, &msg, sizeof(msg)); 138 | if (size == 0) 139 | { 140 | rt_kprintf("can dev write data failed!\n"); 141 | } 142 | 143 | return res; 144 | } 145 | /* 导出到 msh 命令列表中 */ 146 | MSH_CMD_EXPORT(can_sample, can device sample); 147 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------