4
0
mirror of https://github.com/RT-Thread/rt-thread.git synced 2025-01-30 05:10:26 +08:00

add driver example

This commit is contained in:
wangyq2018 2020-12-16 16:31:01 +08:00
parent a51e137c91
commit d9387959cd
56 changed files with 3876 additions and 1 deletions

View File

@ -110,7 +110,7 @@ msh >
## 4. 联系人信息
- [wangyongquan](https://github.com/wangyq2018)
- [liuhongyan](https://gitee.com/liuhongyan98)
## 5. 参考

View File

@ -0,0 +1,52 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

View File

@ -0,0 +1,47 @@
# 外设驱动测试用例
## 1、介绍
这个软件包包含一些外设设备操作的例程。
### 1.1 例程说明
| 文件 | 说明 |
| ---------------- | ------------------------------- |
| adc_vol_sample.c | 使用 ADC 设备转换电压数据 |
| can_sample.c | 通过 CAN 设备发送一帧,并创建一个线程接收数据然后打印输出。 |
| hwtimer_sample.c | 使用 硬件定时器定时 |
| i2c_sample.c | 使用 i2c 设备进行读写 |
| pm.c | 反复进入不同程度的睡眠。 |
| led_blink_sample.c | 使用 pin 设备控制 LED 闪烁 |
| pin_beep_sample.c | 使用 pin 设备控制蜂鸣器 |
| pwm_led_sample.c | 使用 pwm 设备控制 LED 的亮度 |
| rtc_sample.c | 使用 rtc 设备设置年月日时分秒信息 |
| spi_sample.c | 使用 spi 设备进行读写 |
| uart_sample.c | 使用 serial 设备中断接收及轮询发送模式收发数据 |
### 1.2 依赖
依赖设备管理模块提供的设备驱动。
## 2、如何打开 外设驱动测试用例
使用 外设驱动测试用例 需要在 RT-Thread 的menuconfig中选择它具体路径如下
```
Hardware Driver Config --->
Peripheral Driver test example--->
```
## 3、使用 外设驱动测试用例
在打开 Peripheral Driver test example 后,当进行 BSP 编译时,选择的软件包相关源代码会被加入到 BSP 工程中进行编译。
## 4、注意事项
暂无。
## 5、联系方式 & 感谢
* 维护:[misonyo](https://github.com/misonyo)
* 主页https://github.com/RT-Thread-packages/peripheral-sample

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-29 misonyo first implementation.
*/
/*
* ADC 使
* adc_sample
* adc_sample
* ADC
* 3.3V,12
*/
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "adc0" /* ADC 设备名称 */
#define ADC_DEV_CHANNEL 5 /* PA1 ADC 通道 */
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */
static int adc_vol_sample(int argc, char *argv[])
{
rt_adc_device_t adc_dev;
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK;
/* 查找设备 */
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
if (adc_dev == RT_NULL)
{
rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
return RT_ERROR;
}
/* 使能设备 */
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
/* 读取采样值 */
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
rt_kprintf("the value is :%d \n", value);
/* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
/* 关闭通道 */
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-06-25 misonyo first implementation.
*/
/*
* CAN 使
* can_sample
* can_sample can2
* 使 CAN 使 CAN
* CAN 线
*/
#include <rtthread.h>
#include "rtdevice.h"
#define CAN_DEV_NAME "can2" /* CAN 设备名称 */
static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */
static rt_device_t can_dev; /* CAN 设备句柄 */
/* 接收数据回调函数 */
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
{
/* CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void can_rx_thread(void *parameter)
{
int i;
struct rt_can_msg rxmsg = {0};
/* 设置接收回调函数 */
rt_device_set_rx_indicate(can_dev, can_rx_call);
#ifdef RT_CAN_USING_HDR
rt_err_t res;
struct rt_can_filter_item items[5] =
{
RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ffhdr为-1设置默认过滤表 */
RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ffhdr为-1 */
RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211hdr为-1 */
RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), /* std,match ID:0x486hdr为-1 */
{0x555, 0, 0, 0, 0x7ff, 7,} /* std,match ID:0x555hdr为7指定设置7号过滤表 */
};
struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有5个过滤表 */
/* 设置硬件过滤表 */
res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
RT_ASSERT(res == RT_EOK);
#endif
while (1)
{
/* hdr值为-1表示直接从uselist链表读取数据 */
rxmsg.hdr = -1;
/* 阻塞等待接收信号量 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
/* 从CAN读取一帧数据 */
rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
/* 打印数据ID及内容 */
rt_kprintf("ID:%x ", rxmsg.id);
for (i = 0; i < 8; i++)
{
rt_kprintf("%2x ", rxmsg.data[i]);
}
rt_kprintf("\n");
}
}
int can_sample(int argc, char *argv[])
{
struct rt_can_msg msg = {0};
rt_err_t res;
rt_size_t size;
rt_thread_t thread;
char can_name[RT_NAME_MAX];
if (argc == 2)
{
rt_strncpy(can_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
}
can_dev = rt_device_find(can_name);
if (!can_dev)
{
rt_kprintf("find %s failed!\n", can_name);
return RT_ERROR;
}
/* 初始化CAN接收信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以中断接收及发送方式打开CAN设备 */
res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
RT_ASSERT(res == RT_EOK);
thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create can_rx thread failed!\n");
}
msg.id = 0x78; /* ID为0x78 */
msg.ide = RT_CAN_STDID; /* 标准格式 */
msg.rtr = RT_CAN_DTR; /* 数据帧 */
msg.len = 8; /* 数据长度为8 */
/* 待发送的8字节数据 */
msg.data[0] = 0x00;
msg.data[1] = 0x11;
msg.data[2] = 0x22;
msg.data[3] = 0x33;
msg.data[4] = 0x44;
msg.data[5] = 0x55;
msg.data[6] = 0x66;
msg.data[7] = 0x77;
/* 发送一帧CAN数据 */
size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
if (size == 0)
{
rt_kprintf("can dev write data failed!\n");
}
return res;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(can_sample, can device sample);

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-30 misonyo first implementation.
*/
/*
* hwtimer 使
* hwtimer_sample
* hwtimer_sample
* tick值2tick值之差换算为时间等同于定时时间值
*/
#include <rtthread.h>
#include <rtdevice.h>
#define HWTIMER_DEV_NAME "timer0" /* 定时器名称 */
/* 定时器超时回调函数 */
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
rt_kprintf("tick is :%d !\n", rt_tick_get());
return 0;
}
static int hwtimer_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
rt_hwtimerval_t timeout_s; /* 定时器超时值 */
rt_device_t hw_dev = RT_NULL; /* 定时器设备句柄 */
rt_hwtimer_mode_t mode; /* 定时器模式 */
/* 查找定时器设备 */
hw_dev = rt_device_find(HWTIMER_DEV_NAME);
if (hw_dev == RT_NULL)
{
rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
return RT_ERROR;
}
/* 以读写方式打开设备 */
ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
if (ret != RT_EOK)
{
rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);
return ret;
}
/* 设置超时回调函数 */
rt_device_set_rx_indicate(hw_dev, timeout_cb);
/* 设置模式为周期性定时器 */
mode = HWTIMER_MODE_PERIOD;
ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
if (ret != RT_EOK)
{
rt_kprintf("set mode failed! ret is :%d\n", ret);
return ret;
}
/* 设置定时器超时值为5s并启动定时器 */
timeout_s.sec = 5; /* 秒 */
timeout_s.usec = 0; /* 微秒 */
if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
{
rt_kprintf("set timeout value failed\n");
return RT_ERROR;
}
/* 延时3500ms */
rt_thread_mdelay(3500);
/* 读取定时器当前值 */
rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample);

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* I2C 使
* i2c_io_sample
* i2c_io_sample
* 使I2C总线设备
* I2C 1
*/
#include <rtthread.h>
#include <rtdevice.h>
#define I2C_BUS_NAME "i2c1" /* I2C总线设备名称 */
#define SLAVE_ADDR 0x2D /* 从机地址 */
#define STR_LEN 16 /* 接收发送的数据长度 */
static void i2c_io_sample(int argc, char *argv[])
{
struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
struct rt_i2c_msg temp_msg; /* I2C消息 */
rt_uint8_t buffer[STR_LEN] = { 0U };
rt_uint32_t i,num_msg;
rt_size_t s_stat;
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C_BUS_NAME); /* 通过名字获取I2C总线设备的句柄 */
if( i2c_bus == RT_NULL)
{
rt_kprintf("can't find i2c device :%s !\n",I2C_BUS_NAME);
return;
}
/*初始化消息*/
temp_msg.addr = SLAVE_ADDR; /* 从机地址 */
temp_msg.len = STR_LEN; /* 传输的数据长度 */
temp_msg.buf = buffer; /* 读写缓存器 */
num_msg = 1; /* 传输一条消息 */
temp_msg.flags = RT_I2C_RD; /* I2C读 */
s_stat = rt_i2c_transfer(i2c_bus,&temp_msg,num_msg); /* 传输消息 */
rt_thread_mdelay(400);
if( s_stat == num_msg )
{
rt_kprintf("receive successful. \n receive messege : %s \n:",buffer);
for( i = 0 ; i < STR_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
}
else
{
rt_kprintf("device s% recieve fail \n buffer : s%\n",I2C_BUS_NAME,buffer);
return;
}
for( i = 0 ; i < STR_LEN ; i++)
buffer[i]++;
temp_msg.flags = RT_I2C_WR; /* I2C写 */
s_stat = rt_i2c_transfer(i2c_bus,&temp_msg,num_msg); /* 传输一条 */
rt_thread_mdelay(400);
if( s_stat == num_msg )
{
rt_kprintf(" send successful \n messege : %s \n:",buffer);
for( i = 0 ; i < STR_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
}
else
{
rt_kprintf("device s% send fail \n",I2C_BUS_NAME);
return;
}
return;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(i2c_io_sample, i2c io sample);

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-09-25 misonyo first edition.
*/
/*
* PIN脚控制LED亮灭的使用例程
* led_sample
* led_sample
* 使PIN脚编号使
* led线程线1000ms改变PIN脚状态led灯
*
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <stdlib.h>
/* PIN脚编号查看驱动文件drv_gpio.c确定 */
#define LED_PIN_NUM 45 /*PA12*/
static int pin_num;
static void led_entry(void *parameter)
{
int count = 0;
/* 设置PIN脚模式为输出 */
rt_pin_mode(pin_num, PIN_MODE_OUTPUT);
while (1)
{
count++;
rt_kprintf("thread run count : %d\r\n", count);
/* 拉低PIN脚 */
rt_pin_write(pin_num, PIN_LOW);
rt_kprintf("led on!\r\n");
/* 延时1000ms */
rt_thread_mdelay(1000);
/* 拉高PIN脚 */
rt_pin_write(pin_num, PIN_HIGH);
rt_kprintf("led off!\r\n");
rt_thread_mdelay(1000);
}
}
static int led_sample(int argc, char *argv[])
{
rt_thread_t tid;
rt_err_t ret = RT_EOK;
/* 判断命令行参数是否给定了PIN脚编号 */
if (argc == 2)
{
pin_num = atoi(argv[1]);
}
else
{
pin_num = LED_PIN_NUM;
}
tid = rt_thread_create("led",
led_entry,
RT_NULL,
512,
RT_THREAD_PRIORITY_MAX / 3,
20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(led_sample, led sample);

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* PIN 使
* pin_beep_sample
* pin_beep_sample
*
*/
#include <rtthread.h>
#include <rtdevice.h>
/* 引脚编号通过查看驱动文件drv_gpio.c确定 */
#ifndef BEEP_PIN_NUM
#define BEEP_PIN_NUM 45 /* PA12 */
#endif
#ifndef KEY0_PIN_NUM
#define KEY0_PIN_NUM 18 /* PF0 */
#endif
#ifndef KEY1_PIN_NUM
#define KEY1_PIN_NUM 19 /* PF1 */
#endif
void beep_on(void *args)
{
rt_kprintf("turn on beep!\n");
rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
}
void beep_off(void *args)
{
rt_kprintf("turn off beep!\n");
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
}
static void pin_beep_sample(void)
{
/* 蜂鸣器引脚为输出模式 */
rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
/* 默认低电平 */
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
/* 按键0引脚为输入模式 */
rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为beep_on */
rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);
/* 按键1引脚为输入模式 */
rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为beep_off */
rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE);
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pin_beep_sample, pin beep sample);

View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* pm睡眠唤醒的使用例程
* pm_sample
* pm_sample
*
*
*/
#include <rtthread.h>
#include <rtdevice.h>
#define PM_NAME "pm" /* 设备名称 */
#define WAKE_UP_PIN 18 /* 唤醒源 */
#define SLEEP_TIMES 12 /* 进入睡眠次数,轮流进入不同的睡眠模式,包括无睡眠模式 */
struct pm_callback_t
{
volatile int in_fun_times; /*进入函数的次数*/
volatile char flag; /*标志*/
volatile int mode; /*需要打印的模式*/
};
volatile struct pm_callback_t g_pm_data;
/*进入睡眠前,睡眠唤醒后,都会进入。*/
/*函数打印睡眠相关的信息*/
void sleep_in_out_callback(rt_uint8_t event, rt_uint8_t mode, void *data)
{
/*没有标志,不处理*/
if(!(g_pm_data.flag))
{
return;
}
/*标志不正常,清空标志*/
if((g_pm_data.flag) > 2)
{
(g_pm_data.flag) = 0;
return;
}
/*模式不匹配*/
if(g_pm_data.mode != mode )
{
return;
}
/*进入的事件*/
switch(event)
{
/*进入睡眠前*/
case RT_PM_ENTER_SLEEP: g_pm_data.flag = 1;
rt_kprintf("\n\r##%d : ENTER ",g_pm_data.in_fun_times);
g_pm_data.in_fun_times++; /*进入睡眠次数+1*/
break;
/*睡眠唤醒后*/
case RT_PM_EXIT_SLEEP: g_pm_data.flag = 0; /*睡眠唤醒后*/
rt_kprintf("\n\rEXIT\n\r");
rt_pm_release(mode); /*释放休眠模式*/
return;
default: break;
};
/*当前的睡眠模式*/
switch(mode)
{
case PM_SLEEP_MODE_NONE: rt_kprintf("PM_SLEEP_MODE_NONE\n\r");
break;
case PM_SLEEP_MODE_IDLE: rt_kprintf("PM_SLEEP_MODE_IDLE\n\r");
break;
case PM_SLEEP_MODE_LIGHT: rt_kprintf("PM_SLEEP_MODE_LIGHT\n\r");
break;
case PM_SLEEP_MODE_DEEP: rt_kprintf("PM_SLEEP_MODE_DEEP\n\r");
break;
case PM_SLEEP_MODE_STANDBY: rt_kprintf("PM_SLEEP_MODE_STANDBY\n\r");
break;
case PM_SLEEP_MODE_SHUTDOWN: rt_kprintf("PM_SLEEP_MODE_SHUTDOWN\n\r");
break;
case PM_SLEEP_MODE_MAX: rt_kprintf("PM_SLEEP_MODE_MAX\n\r");
break;
default: break;
}
}
/* pm测试函数 */
static void pm_test(void *parameter)
{
int in_mode[7],i = 0;
g_pm_data.in_fun_times = 0;
g_pm_data.flag = 0;
in_mode[0] = PM_SLEEP_MODE_NONE;
in_mode[1] = PM_SLEEP_MODE_IDLE;
in_mode[2] = PM_SLEEP_MODE_LIGHT;
in_mode[3] = PM_SLEEP_MODE_DEEP;
in_mode[4] = PM_SLEEP_MODE_STANDBY;
in_mode[5] = PM_SLEEP_MODE_SHUTDOWN;
in_mode[6] = PM_SLEEP_MODE_MAX;
/*设置回调函数和私有数据*/
rt_pm_notify_set(sleep_in_out_callback,RT_NULL);
while(i < SLEEP_TIMES)
{
g_pm_data.mode = in_mode[i%6];
/*无休眠模式,不赋予标志*/
if(g_pm_data.mode != PM_SLEEP_MODE_NONE)
{
g_pm_data.flag = 2;
}
/*请求选择的休眠模式*/
rt_pm_request(in_mode[i%6]);
rt_thread_mdelay(500);
/*无休眠模式,不需要额外的等待*/
while(( g_pm_data.flag != 0 )&&(g_pm_data.mode != PM_SLEEP_MODE_NONE))
{
rt_thread_mdelay(500);
}
/*释放选择的休眠模式*/
rt_pm_release(in_mode[i%6]);
i++;
}
/*清除回调函数和私有数据*/
rt_pm_notify_set(RT_NULL,RT_NULL);
rt_kprintf("thread pm_test close\n\r");
}
/*按键唤醒的回调函数*/
void wake_by_pin(void *args)
{
}
static int pm_sample(int argc, char *argv[])
{
rt_thread_t thread;
/* 按键引脚为输入模式 */
rt_pin_mode(WAKE_UP_PIN, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为wake_by_pin */
rt_pin_attach_irq(WAKE_UP_PIN, PIN_IRQ_MODE_RISING, wake_by_pin, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(WAKE_UP_PIN, PIN_IRQ_ENABLE);
thread = rt_thread_create("pm_test", pm_test, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create pm_test thread failed!\n\r");
}
return RT_EOK;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pm_sample, pm sample);

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-25 misonyo first implementation.
*/
/*
* PWM 使
* pwm_led_sample
* pwm_led_sample
* PWM LED LED不停的由暗变到亮
*/
#include <rtthread.h>
#include <rtdevice.h>
#define LED_PIN_NUM 45 /* PA12 LED PIN脚编号查看驱动文件drv_gpio.c确定 */
#define PWM_DEV_NAME "pwm0" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 2 /* PA9 PWM通道 */
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
static int pwm_led_sample(int argc, char *argv[])
{
rt_uint32_t period, pulse, dir;
period = 500000; /* 周期为0.5ms单位为纳秒ns */
dir = 1; /* PWM脉冲宽度值的增减方向 */
pulse = 0; /* PWM脉冲宽度值单位为纳秒ns */
/* 查找设备 */
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
if (pwm_dev == RT_NULL)
{
rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);
return RT_ERROR;
}
/* 设置PWM周期和脉冲宽度默认值 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
/* 使能设备 */
rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
while (1)
{
rt_thread_mdelay(50);
if (dir)
{
pulse += 5000; /* 从0值开始每次增加5000ns */
}
else
{
pulse -= 5000; /* 从最大值开始每次减少5000ns */
}
if (pulse >= period)
{
dir = 0;
}
if (0 == pulse)
{
dir = 1;
}
/* 设置PWM周期和脉冲宽度 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pwm_led_sample, pwm sample);

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-30 misonyo first implementation.
*/
/*
* RTC 使
* rtc_sample
* rtc_sample
* RTC设备的日期和时间
*/
#include <rtthread.h>
#include <rtdevice.h>
static int rtc_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
time_t now;
/* 设置日期 */
ret = set_date(2018, 12, 3);
if (ret != RT_EOK)
{
rt_kprintf("set RTC date failed\n");
return ret;
}
/* 设置时间 */
ret = set_time(11, 15, 50);
if (ret != RT_EOK)
{
rt_kprintf("set RTC time failed\n");
return ret;
}
/* 延时3秒 */
rt_thread_mdelay(3000);
/* 获取时间 */
now = time(RT_NULL);
rt_kprintf("%s\n", ctime(&now));
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(rtc_sample, rtc sample);

View File

@ -0,0 +1,152 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* SPI 使
* spi_io_sample
* spi_io_sample
* SPI设备先读取数据1
*/
#include <rtthread.h>
#include <rtdevice.h>
#define SPI_DEVICE_NAME "spi00"
#define BUF_LEN 16
static void spi_io_sample(int argc, char *argv[])
{
struct rt_spi_device * spi_dev; /* spi设备的句柄 */
struct rt_spi_configuration spi_config;
rt_uint8_t i,buffer[BUF_LEN] = { 0U };
rt_err_t s_stat;
rt_err_t result;
/* 查找 spi设备 获取spi设备句柄 */
spi_dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
if (spi_dev == RT_NULL)
{
rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_DEVICE_NAME);
return;
}
/* 清空配置结构体 */
rt_memset(&spi_config,0,sizeof(struct rt_spi_configuration));
spi_config.mode &= ~RT_SPI_SLAVE; /* 主机模式 */
spi_config.mode &= ~RT_SPI_3WIRE; /* 4线双向传输 */
spi_config.mode |= RT_SPI_CPHA; /* 第二边沿采样 */
spi_config.mode |= RT_SPI_CPOL; /* 空闲高电平 */
spi_config.mode |= RT_SPI_NO_CS; /* 禁用软件从机选择管理 */
spi_config.mode |= RT_SPI_MSB; /* 高位在前 */
spi_config.data_width = 8; /* 数据长度8 */
spi_config.max_hz = 2000000; /* 最快时钟频率 */
/* 配置SPI设备 */
s_stat = rt_spi_configure(spi_dev,&spi_config);
if(s_stat != RT_EOK)
{
rt_kprintf(" spi config fail !\n ");
return;
}
/* 获取总线 ,防止总线被多个线程同时使用 */
result = rt_spi_take_bus(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s take spi bus failed! \n", SPI_DEVICE_NAME);
return;
}
/* 选中片选 */
result = rt_spi_take(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s take spi cs failed! \n", SPI_DEVICE_NAME);
return;
}
/*接收一次数据*/
result = rt_spi_recv(spi_dev,buffer,BUF_LEN);
if(result != BUF_LEN)
{
rt_kprintf("receive fail. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
return;
}
rt_kprintf("receive successful. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
/* 将接收到的数据加1 */
for( i = 0 ; i < BUF_LEN ; i++)
buffer[i]++;
/*发送数据*/
result = rt_spi_send(spi_dev,buffer,BUF_LEN);
if(result != BUF_LEN)
{
rt_kprintf("send fail. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
return;
}
rt_kprintf("send successful. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
/* 释放片选 */
result = rt_spi_release(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s release spi cs failed! \n", SPI_DEVICE_NAME);
return;
}
/* 释放总线 */
result = rt_spi_release_bus(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s release spi bus failed! \n", SPI_DEVICE_NAME);
return;
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(spi_io_sample, spi sample);

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* 使
* uart_sample
* uart_sample uart2
* 使使
* "hello RT-Thread!"
*/
#include <rtthread.h>
#define SAMPLE_UART_NAME "uart1" /* 串口设备名称 */
/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial;
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
/* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial_thread_entry(void *parameter)
{
char ch;
while (1)
{
/* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
/* 阻塞等待接收信号量,等到信号量后再次读取数据 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/* 读取到的数据通过串口错位输出 */
ch = ch + 1;
rt_device_write(serial, 0, &ch, 1);
}
}
static int uart_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
char uart_name[RT_NAME_MAX];
char str[] = "hello RT-Thread!\r\n";
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
/* 查找串口设备 */
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return RT_ERROR;
}
/* 初始化信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以中断接收及轮询发送方式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial, uart_input);
/* 发送字符串 */
rt_device_write(serial, 0, str, (sizeof(str) - 1));
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_sample, uart device sample);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,52 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

View File

@ -0,0 +1,47 @@
# 外设驱动测试用例
## 1、介绍
这个软件包包含一些外设设备操作的例程。
### 1.1 例程说明
| 文件 | 说明 |
| ---------------- | ------------------------------- |
| adc_vol_sample.c | 使用 ADC 设备转换电压数据 |
| can_sample.c | 通过 CAN 设备发送一帧,并创建一个线程接收数据然后打印输出。 |
| hwtimer_sample.c | 使用 硬件定时器定时 |
| i2c_sample.c | 使用 i2c 设备进行读写 |
| pm.c | 反复进入不同程度的睡眠。 |
| led_blink_sample.c | 使用 pin 设备控制 LED 闪烁 |
| pin_beep_sample.c | 使用 pin 设备控制蜂鸣器 |
| pwm_led_sample.c | 使用 pwm 设备控制 LED 的亮度 |
| rtc_sample.c | 使用 rtc 设备设置年月日时分秒信息 |
| spi_sample.c | 使用 spi 设备进行读写 |
| uart_sample.c | 使用 serial 设备中断接收及轮询发送模式收发数据 |
### 1.2 依赖
依赖设备管理模块提供的设备驱动。
## 2、如何打开 外设驱动测试用例
使用 外设驱动测试用例 需要在 RT-Thread 的menuconfig中选择它具体路径如下
```
Hardware Driver Config --->
Peripheral Driver test example--->
```
## 3、使用 外设驱动测试用例
在打开 Peripheral Driver test example 后,当进行 BSP 编译时,选择的软件包相关源代码会被加入到 BSP 工程中进行编译。
## 4、注意事项
暂无。
## 5、联系方式 & 感谢
* 维护:[misonyo](https://github.com/misonyo)
* 主页https://github.com/RT-Thread-packages/peripheral-sample

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-29 misonyo first implementation.
*/
/*
* ADC 使
* adc_sample
* adc_sample
* ADC
* 3.3V,12
*/
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "adc0" /* ADC 设备名称 */
#define ADC_DEV_CHANNEL 5 /* PA1 ADC 通道 */
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */
static int adc_vol_sample(int argc, char *argv[])
{
rt_adc_device_t adc_dev;
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK;
/* 查找设备 */
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
if (adc_dev == RT_NULL)
{
rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
return RT_ERROR;
}
/* 使能设备 */
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
/* 读取采样值 */
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
rt_kprintf("the value is :%d \n", value);
/* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
/* 关闭通道 */
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-06-25 misonyo first implementation.
*/
/*
* CAN 使
* can_sample
* can_sample can2
* 使 CAN 使 CAN
* CAN 线
*/
#include <rtthread.h>
#include "rtdevice.h"
#define CAN_DEV_NAME "can" /* CAN 设备名称 */
static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */
static rt_device_t can_dev; /* CAN 设备句柄 */
/* 接收数据回调函数 */
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
{
/* CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void can_rx_thread(void *parameter)
{
int i;
struct rt_can_msg rxmsg = {0};
/* 设置接收回调函数 */
rt_device_set_rx_indicate(can_dev, can_rx_call);
#ifdef RT_CAN_USING_HDR
rt_err_t res;
struct rt_can_filter_item items[5] =
{
RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ffhdr为-1设置默认过滤表 */
RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ffhdr为-1 */
RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211hdr为-1 */
RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), /* std,match ID:0x486hdr为-1 */
{0x555, 0, 0, 0, 0x7ff, 7,} /* std,match ID:0x555hdr为7指定设置7号过滤表 */
};
struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有5个过滤表 */
/* 设置硬件过滤表 */
res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
RT_ASSERT(res == RT_EOK);
#endif
while (1)
{
/* hdr值为-1表示直接从uselist链表读取数据 */
rxmsg.hdr = -1;
/* 阻塞等待接收信号量 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
/* 从CAN读取一帧数据 */
rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
/* 打印数据ID及内容 */
rt_kprintf("ID:%x ", rxmsg.id);
for (i = 0; i < 8; i++)
{
rt_kprintf("%2x ", rxmsg.data[i]);
}
rt_kprintf("\n");
}
}
int can_sample(int argc, char *argv[])
{
struct rt_can_msg msg = {0};
rt_err_t res;
rt_size_t size;
rt_thread_t thread;
char can_name[RT_NAME_MAX];
if (argc == 2)
{
rt_strncpy(can_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
}
can_dev = rt_device_find(can_name);
if (!can_dev)
{
rt_kprintf("find %s failed!\n", can_name);
return RT_ERROR;
}
/* 初始化CAN接收信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以中断接收及发送方式打开CAN设备 */
res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
RT_ASSERT(res == RT_EOK);
thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create can_rx thread failed!\n");
}
msg.id = 0x78; /* ID为0x78 */
msg.ide = RT_CAN_STDID; /* 标准格式 */
msg.rtr = RT_CAN_DTR; /* 数据帧 */
msg.len = 8; /* 数据长度为8 */
/* 待发送的8字节数据 */
msg.data[0] = 0x00;
msg.data[1] = 0x11;
msg.data[2] = 0x22;
msg.data[3] = 0x33;
msg.data[4] = 0x44;
msg.data[5] = 0x55;
msg.data[6] = 0x66;
msg.data[7] = 0x77;
/* 发送一帧CAN数据 */
size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
if (size == 0)
{
rt_kprintf("can dev write data failed!\n");
}
return res;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(can_sample, can device sample);

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-30 misonyo first implementation.
*/
/*
* hwtimer 使
* hwtimer_sample
* hwtimer_sample
* tick值2tick值之差换算为时间等同于定时时间值
*/
#include <rtthread.h>
#include <rtdevice.h>
#define HWTIMER_DEV_NAME "timer0" /* 定时器名称 */
/* 定时器超时回调函数 */
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
rt_kprintf("tick is :%d !\n", rt_tick_get());
return 0;
}
static int hwtimer_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
rt_hwtimerval_t timeout_s; /* 定时器超时值 */
rt_device_t hw_dev = RT_NULL; /* 定时器设备句柄 */
rt_hwtimer_mode_t mode; /* 定时器模式 */
/* 查找定时器设备 */
hw_dev = rt_device_find(HWTIMER_DEV_NAME);
if (hw_dev == RT_NULL)
{
rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
return RT_ERROR;
}
/* 以读写方式打开设备 */
ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
if (ret != RT_EOK)
{
rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);
return ret;
}
/* 设置超时回调函数 */
rt_device_set_rx_indicate(hw_dev, timeout_cb);
/* 设置模式为周期性定时器 */
mode = HWTIMER_MODE_PERIOD;
ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
if (ret != RT_EOK)
{
rt_kprintf("set mode failed! ret is :%d\n", ret);
return ret;
}
/* 设置定时器超时值为5s并启动定时器 */
timeout_s.sec = 5; /* 秒 */
timeout_s.usec = 0; /* 微秒 */
if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
{
rt_kprintf("set timeout value failed\n");
return RT_ERROR;
}
/* 延时3500ms */
rt_thread_mdelay(3500);
/* 读取定时器当前值 */
rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample);

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* I2C 使
* i2c_io_sample
* i2c_io_sample
* 使I2C总线设备
* I2C 1
*/
#include <rtthread.h>
#include <rtdevice.h>
#define I2C_BUS_NAME "i2c1" /* I2C总线设备名称 */
#define SLAVE_ADDR 0x2D /* 从机地址 */
#define STR_LEN 16 /* 接收发送的数据长度 */
static void i2c_io_sample(int argc, char *argv[])
{
struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
struct rt_i2c_msg temp_msg; /* I2C消息 */
rt_uint8_t buffer[STR_LEN] = { 0U };
rt_uint32_t i,num_msg;
rt_size_t s_stat;
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C_BUS_NAME); /* 通过名字获取I2C总线设备的句柄 */
if( i2c_bus == RT_NULL)
{
rt_kprintf("can't find i2c device :%s !\n",I2C_BUS_NAME);
return;
}
/*初始化消息*/
temp_msg.addr = SLAVE_ADDR; /* 从机地址 */
temp_msg.len = STR_LEN; /* 传输的数据长度 */
temp_msg.buf = buffer; /* 读写缓存器 */
num_msg = 1; /* 传输一条消息 */
temp_msg.flags = RT_I2C_RD; /* I2C读 */
s_stat = rt_i2c_transfer(i2c_bus,&temp_msg,num_msg); /* 传输消息 */
rt_thread_mdelay(400);
if( s_stat == num_msg )
{
rt_kprintf("receive successful. \n receive messege : %s \n:",buffer);
for( i = 0 ; i < STR_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
}
else
{
rt_kprintf("device s% recieve fail \n buffer : s%\n",I2C_BUS_NAME,buffer);
return;
}
for( i = 0 ; i < STR_LEN ; i++)
buffer[i]++;
temp_msg.flags = RT_I2C_WR; /* I2C写 */
s_stat = rt_i2c_transfer(i2c_bus,&temp_msg,num_msg); /* 传输一条 */
rt_thread_mdelay(400);
if( s_stat == num_msg )
{
rt_kprintf(" send successful \n messege : %s \n:",buffer);
for( i = 0 ; i < STR_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
}
else
{
rt_kprintf("device s% send fail \n",I2C_BUS_NAME);
return;
}
return;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(i2c_io_sample, i2c io sample);

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-09-25 misonyo first edition.
*/
/*
* PIN脚控制LED亮灭的使用例程
* led_sample
* led_sample 41
* 使PIN脚编号使
* led线程线1000ms改变PIN脚状态led灯
*
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <stdlib.h>
/* PIN脚编号查看驱动文件drv_gpio.c确定 */
#define LED_PIN_NUM 40 /*PB9*/
static int pin_num;
static void led_entry(void *parameter)
{
int count = 0;
/* 设置PIN脚模式为输出 */
rt_pin_mode(pin_num, PIN_MODE_OUTPUT);
while (1)
{
count++;
rt_kprintf("thread run count : %d\r\n", count);
/* 拉低PIN脚 */
rt_pin_write(pin_num, PIN_LOW);
rt_kprintf("led on!\r\n");
/* 延时1000ms */
rt_thread_mdelay(1000);
/* 拉高PIN脚 */
rt_pin_write(pin_num, PIN_HIGH);
rt_kprintf("led off!\r\n");
rt_thread_mdelay(1000);
}
}
static int led_sample(int argc, char *argv[])
{
rt_thread_t tid;
rt_err_t ret = RT_EOK;
/* 判断命令行参数是否给定了PIN脚编号 */
if (argc == 2)
{
pin_num = atoi(argv[1]);
}
else
{
pin_num = LED_PIN_NUM;
}
tid = rt_thread_create("led",
led_entry,
RT_NULL,
512,
RT_THREAD_PRIORITY_MAX / 3,
20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(led_sample, led sample);

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* PIN 使
* pin_beep_sample
* pin_beep_sample
*
*/
#include <rtthread.h>
#include <rtdevice.h>
/* 引脚编号通过查看驱动文件drv_gpio.c确定 */
#ifndef BEEP_PIN_NUM
#define BEEP_PIN_NUM 40 /* PB9 */
#endif
#ifndef KEY0_PIN_NUM
#define KEY0_PIN_NUM 18 /* PF0 */
#endif
#ifndef KEY1_PIN_NUM
#define KEY1_PIN_NUM 19 /* PF1 */
#endif
void beep_on(void *args)
{
rt_kprintf("turn on beep!\n");
rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
}
void beep_off(void *args)
{
rt_kprintf("turn off beep!\n");
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
}
static void pin_beep_sample(void)
{
/* 蜂鸣器引脚为输出模式 */
rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
/* 默认低电平 */
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
/* 按键0引脚为输入模式 */
rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为beep_on */
rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);
/* 按键1引脚为输入模式 */
rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为beep_off */
rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE);
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pin_beep_sample, pin beep sample);

View File

@ -0,0 +1,183 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* pm睡眠唤醒的使用例程
* pm_sample
* pm_sample
*
*
*/
#include <rtthread.h>
#include <rtdevice.h>
#define PM_NAME "pm" /* 设备名称 */
#define WAKE_UP_PIN 18 /* 唤醒源 */
#define SLEEP_TIMES 12 /* 进入睡眠次数,轮流进入不同的睡眠模式,包括无睡眠模式 */
struct pm_callback_t
{
volatile int in_fun_times; /*进入函数的次数*/
volatile char flag; /*标志*/
volatile int mode; /*需要打印的模式*/
};
volatile struct pm_callback_t g_pm_data;
/*进入睡眠前,睡眠唤醒后,都会进入。*/
/*函数打印睡眠相关的信息*/
void sleep_in_out_callback(rt_uint8_t event, rt_uint8_t mode, void *data)
{
/*没有标志,不处理*/
if(!(g_pm_data.flag))
{
return;
}
/*标志不正常,清空标志*/
if((g_pm_data.flag) > 2)
{
(g_pm_data.flag) = 0;
return;
}
/*模式不匹配*/
if(g_pm_data.mode != mode )
{
return;
}
/*进入的事件*/
switch(event)
{
/*进入睡眠前*/
case RT_PM_ENTER_SLEEP: g_pm_data.flag = 1;
rt_kprintf("\n\r##%d : ENTER ",g_pm_data.in_fun_times);
g_pm_data.in_fun_times++; /*进入睡眠次数+1*/
break;
/*睡眠唤醒后*/
case RT_PM_EXIT_SLEEP: g_pm_data.flag = 0; /*睡眠唤醒后*/
rt_kprintf("\n\rEXIT\n\r");
rt_pm_release(mode); /*释放休眠模式*/
return;
default: break;
};
/*当前的睡眠模式*/
switch(mode)
{
case PM_SLEEP_MODE_NONE: rt_kprintf("PM_SLEEP_MODE_NONE\n\r");
break;
case PM_SLEEP_MODE_IDLE: rt_kprintf("PM_SLEEP_MODE_IDLE\n\r");
break;
case PM_SLEEP_MODE_LIGHT: rt_kprintf("PM_SLEEP_MODE_LIGHT\n\r");
break;
case PM_SLEEP_MODE_DEEP: rt_kprintf("PM_SLEEP_MODE_DEEP\n\r");
break;
case PM_SLEEP_MODE_STANDBY: rt_kprintf("PM_SLEEP_MODE_STANDBY\n\r");
break;
case PM_SLEEP_MODE_SHUTDOWN: rt_kprintf("PM_SLEEP_MODE_SHUTDOWN\n\r");
break;
case PM_SLEEP_MODE_MAX: rt_kprintf("PM_SLEEP_MODE_MAX\n\r");
break;
default: break;
}
}
/* pm测试函数 */
static void pm_test(void *parameter)
{
int in_mode[7],i = 0;
g_pm_data.in_fun_times = 0;
g_pm_data.flag = 0;
in_mode[0] = PM_SLEEP_MODE_NONE;
in_mode[1] = PM_SLEEP_MODE_IDLE;
in_mode[2] = PM_SLEEP_MODE_LIGHT;
in_mode[3] = PM_SLEEP_MODE_DEEP;
in_mode[4] = PM_SLEEP_MODE_STANDBY;
in_mode[5] = PM_SLEEP_MODE_SHUTDOWN;
in_mode[6] = PM_SLEEP_MODE_MAX;
/*设置回调函数和私有数据*/
rt_pm_notify_set(sleep_in_out_callback,RT_NULL);
while(i < SLEEP_TIMES)
{
g_pm_data.mode = in_mode[i%6];
/*无休眠模式,不赋予标志*/
if(g_pm_data.mode != PM_SLEEP_MODE_NONE)
{
g_pm_data.flag = 2;
}
/*请求选择的休眠模式*/
rt_pm_request(in_mode[i%6]);
rt_thread_mdelay(500);
/*无休眠模式,不需要额外的等待*/
while(( g_pm_data.flag != 0 )&&(g_pm_data.mode != PM_SLEEP_MODE_NONE))
{
rt_thread_mdelay(500);
}
/*释放选择的休眠模式*/
rt_pm_release(in_mode[i%6]);
i++;
}
/*清除回调函数和私有数据*/
rt_pm_notify_set(RT_NULL,RT_NULL);
rt_kprintf("thread pm_test close\n\r");
}
/*按键唤醒的回调函数*/
void wake_by_pin(void *args)
{
}
static int pm_sample(int argc, char *argv[])
{
rt_thread_t thread;
/* 按键引脚为输入模式 */
rt_pin_mode(WAKE_UP_PIN, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为wake_by_pin */
rt_pin_attach_irq(WAKE_UP_PIN, PIN_IRQ_MODE_RISING, wake_by_pin, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(WAKE_UP_PIN, PIN_IRQ_ENABLE);
thread = rt_thread_create("pm_test", pm_test, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create pm_test thread failed!\n\r");
}
return RT_EOK;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pm_sample, pm sample);

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-25 misonyo first implementation.
*/
/*
* PWM 使
* pwm_led_sample
* pwm_led_sample
* PWM LED LED不停的由暗变到亮
*/
#include <rtthread.h>
#include <rtdevice.h>
#define LED_PIN_NUM 16 /* LED PIN脚编号查看驱动文件drv_gpio.c确定 */
#define PWM_DEV_NAME "pwm1" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 4 /* PB9 PWM通道 */
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
static int pwm_led_sample(int argc, char *argv[])
{
rt_uint32_t period, pulse, dir;
period = 500000; /* 周期为0.5ms单位为纳秒ns */
dir = 1; /* PWM脉冲宽度值的增减方向 */
pulse = 0; /* PWM脉冲宽度值单位为纳秒ns */
/* 查找设备 */
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
if (pwm_dev == RT_NULL)
{
rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);
return RT_ERROR;
}
/* 设置PWM周期和脉冲宽度默认值 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
/* 使能设备 */
rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
while (1)
{
rt_thread_mdelay(50);
if (dir)
{
pulse += 5000; /* 从0值开始每次增加5000ns */
}
else
{
pulse -= 5000; /* 从最大值开始每次减少5000ns */
}
if (pulse >= period)
{
dir = 0;
}
if (0 == pulse)
{
dir = 1;
}
/* 设置PWM周期和脉冲宽度 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pwm_led_sample, pwm sample);

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-30 misonyo first implementation.
*/
/*
* RTC 使
* rtc_sample
* rtc_sample
* RTC设备的日期和时间
*/
#include <rtthread.h>
#include <rtdevice.h>
static int rtc_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
time_t now;
/* 设置日期 */
ret = set_date(2018, 12, 3);
if (ret != RT_EOK)
{
rt_kprintf("set RTC date failed\n");
return ret;
}
/* 设置时间 */
ret = set_time(11, 15, 50);
if (ret != RT_EOK)
{
rt_kprintf("set RTC time failed\n");
return ret;
}
/* 延时3秒 */
rt_thread_mdelay(3000);
/* 获取时间 */
now = time(RT_NULL);
rt_kprintf("%s\n", ctime(&now));
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(rtc_sample, rtc sample);

View File

@ -0,0 +1,152 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* SPI 使
* spi_io_sample
* spi_io_sample
* SPI设备先读取数据1
*/
#include <rtthread.h>
#include <rtdevice.h>
#define SPI_DEVICE_NAME "spi00"
#define BUF_LEN 16
static void spi_io_sample(int argc, char *argv[])
{
struct rt_spi_device * spi_dev; /* spi设备的句柄 */
struct rt_spi_configuration spi_config;
rt_uint8_t i,buffer[BUF_LEN] = { 0U };
rt_err_t s_stat;
rt_err_t result;
/* 查找 spi设备 获取spi设备句柄 */
spi_dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
if (spi_dev == RT_NULL)
{
rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_DEVICE_NAME);
return;
}
/* 清空配置结构体 */
rt_memset(&spi_config,0,sizeof(struct rt_spi_configuration));
spi_config.mode &= ~RT_SPI_SLAVE; /* 主机模式 */
spi_config.mode &= ~RT_SPI_3WIRE; /* 4线双向传输 */
spi_config.mode |= RT_SPI_CPHA; /* 第二边沿采样 */
spi_config.mode |= RT_SPI_CPOL; /* 空闲高电平 */
spi_config.mode |= RT_SPI_NO_CS; /* 禁用软件从机选择管理 */
spi_config.mode |= RT_SPI_MSB; /* 高位在前 */
spi_config.data_width = 8; /* 数据长度8 */
spi_config.max_hz = 2000000; /* 最快时钟频率 */
/* 配置SPI设备 */
s_stat = rt_spi_configure(spi_dev,&spi_config);
if(s_stat != RT_EOK)
{
rt_kprintf(" spi config fail !\n ");
return;
}
/* 获取总线 ,防止总线被多个线程同时使用 */
result = rt_spi_take_bus(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s take spi bus failed! \n", SPI_DEVICE_NAME);
return;
}
/* 选中片选 */
result = rt_spi_take(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s take spi cs failed! \n", SPI_DEVICE_NAME);
return;
}
/*接收一次数据*/
result = rt_spi_recv(spi_dev,buffer,BUF_LEN);
if(result != BUF_LEN)
{
rt_kprintf("receive fail. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
return;
}
rt_kprintf("receive successful. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
/* 将接收到的数据加1 */
for( i = 0 ; i < BUF_LEN ; i++)
buffer[i]++;
/*发送数据*/
result = rt_spi_send(spi_dev,buffer,BUF_LEN);
if(result != BUF_LEN)
{
rt_kprintf("send fail. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
return;
}
rt_kprintf("send successful. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
/* 释放片选 */
result = rt_spi_release(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s release spi cs failed! \n", SPI_DEVICE_NAME);
return;
}
/* 释放总线 */
result = rt_spi_release_bus(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s release spi bus failed! \n", SPI_DEVICE_NAME);
return;
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(spi_io_sample, spi sample);

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* 使
* uart_sample
* uart_sample uart2
* 使使
* "hello RT-Thread!"
*/
#include <rtthread.h>
#define SAMPLE_UART_NAME "uart2" /* 串口设备名称 */
/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial;
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
/* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial_thread_entry(void *parameter)
{
char ch;
while (1)
{
/* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
/* 阻塞等待接收信号量,等到信号量后再次读取数据 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/* 读取到的数据通过串口错位输出 */
ch = ch + 1;
rt_device_write(serial, 0, &ch, 1);
}
}
static int uart_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
char uart_name[RT_NAME_MAX];
char str[] = "hello RT-Thread!\r\n";
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
/* 查找串口设备 */
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return RT_ERROR;
}
/* 初始化信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以中断接收及轮询发送方式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial, uart_input);
/* 发送字符串 */
rt_device_write(serial, 0, str, (sizeof(str) - 1));
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_sample, uart device sample);

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,52 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

View File

@ -0,0 +1,47 @@
# 外设驱动测试用例
## 1、介绍
这个软件包包含一些外设设备操作的例程。
### 1.1 例程说明
| 文件 | 说明 |
| ---------------- | ------------------------------- |
| adc_vol_sample.c | 使用 ADC 设备转换电压数据 |
| can_sample.c | 通过 CAN 设备发送一帧,并创建一个线程接收数据然后打印输出。 |
| hwtimer_sample.c | 使用 硬件定时器定时 |
| i2c_sample.c | 使用 i2c 设备进行读写 |
| pm.c | 反复进入不同程度的睡眠。 |
| led_blink_sample.c | 使用 pin 设备控制 LED 闪烁 |
| pin_beep_sample.c | 使用 pin 设备控制蜂鸣器 |
| pwm_led_sample.c | 使用 pwm 设备控制 LED 的亮度 |
| rtc_sample.c | 使用 rtc 设备设置年月日时分秒信息 |
| spi_sample.c | 使用 spi 设备进行读写 |
| uart_sample.c | 使用 serial 设备中断接收及轮询发送模式收发数据 |
### 1.2 依赖
依赖设备管理模块提供的设备驱动。
## 2、如何打开 外设驱动测试用例
使用 外设驱动测试用例 需要在 RT-Thread 的menuconfig中选择它具体路径如下
```
Hardware Driver Config --->
Peripheral Driver test example--->
```
## 3、使用 外设驱动测试用例
在打开 Peripheral Driver test example 后,当进行 BSP 编译时,选择的软件包相关源代码会被加入到 BSP 工程中进行编译。
## 4、注意事项
暂无。
## 5、联系方式 & 感谢
* 维护:[misonyo](https://github.com/misonyo)
* 主页https://github.com/RT-Thread-packages/peripheral-sample

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-29 misonyo first implementation.
*/
/*
* ADC 使
* adc_sample
* adc_sample
* ADC
* 3.3V,12
*/
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "adc0" /* ADC 设备名称 */
#define ADC_DEV_CHANNEL 5 /* ADC 通道 5 PA1*/
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */
static int adc_vol_sample(int argc, char *argv[])
{
rt_adc_device_t adc_dev;
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK;
/* 查找设备 */
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
if (adc_dev == RT_NULL)
{
rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
return RT_ERROR;
}
/* 使能设备 */
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
/* 读取采样值 */
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
rt_kprintf("the value is :%d \n", value);
/* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
/* 关闭通道 */
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-06-25 misonyo first implementation.
*/
/*
* CAN 使
* can_sample
* can_sample can
* 使 CAN 使 CAN
* CAN 线
*/
#include <rtthread.h>
#include "rtdevice.h"
#define CAN_DEV_NAME "can" /* CAN 设备名称 */
static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */
static rt_device_t can_dev; /* CAN 设备句柄 */
/* 接收数据回调函数 */
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
{
/* CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void can_rx_thread(void *parameter)
{
int i;
struct rt_can_msg rxmsg = {0};
/* 设置接收回调函数 */
rt_device_set_rx_indicate(can_dev, can_rx_call);
#ifdef RT_CAN_USING_HDR
rt_err_t res;
struct rt_can_filter_item items[5] =
{
RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ffhdr为-1设置默认过滤表 */
RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ffhdr为-1 */
RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211hdr为-1 */
RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), /* std,match ID:0x486hdr为-1 */
{0x555, 0, 0, 0, 0x7ff, 7,} /* std,match ID:0x555hdr为7指定设置7号过滤表 */
};
struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有5个过滤表 */
/* 设置硬件过滤表 */
res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
RT_ASSERT(res == RT_EOK);
#endif
while (1)
{
/* hdr值为-1表示直接从uselist链表读取数据 */
rxmsg.hdr = -1;
/* 阻塞等待接收信号量 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
/* 从CAN读取一帧数据 */
rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
/* 打印数据ID及内容 */
rt_kprintf("ID:%x ", rxmsg.id);
for (i = 0; i < 8; i++)
{
rt_kprintf("%2x ", rxmsg.data[i]);
}
rt_kprintf("\n");
}
}
int can_sample(int argc, char *argv[])
{
struct rt_can_msg msg = {0};
rt_err_t res;
rt_size_t size;
rt_thread_t thread;
char can_name[RT_NAME_MAX];
if (argc == 2)
{
rt_strncpy(can_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
}
can_dev = rt_device_find(can_name);
if (!can_dev)
{
rt_kprintf("find %s failed!\n", can_name);
return RT_ERROR;
}
/* 初始化CAN接收信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以中断接收及发送方式打开CAN设备 */
res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
RT_ASSERT(res == RT_EOK);
thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create can_rx thread failed!\n");
}
msg.id = 0x78; /* ID为0x78 */
msg.ide = RT_CAN_STDID; /* 标准格式 */
msg.rtr = RT_CAN_DTR; /* 数据帧 */
msg.len = 8; /* 数据长度为8 */
/* 待发送的8字节数据 */
msg.data[0] = 0x00;
msg.data[1] = 0x11;
msg.data[2] = 0x22;
msg.data[3] = 0x33;
msg.data[4] = 0x44;
msg.data[5] = 0x55;
msg.data[6] = 0x66;
msg.data[7] = 0x77;
/* 发送一帧CAN数据 */
size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
if (size == 0)
{
rt_kprintf("can dev write data failed!\n");
}
return res;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(can_sample, can device sample);

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-30 misonyo first implementation.
*/
/*
* hwtimer 使
* hwtimer_sample
* hwtimer_sample
* tick值2tick值之差换算为时间等同于定时时间值
*/
#include <rtthread.h>
#include <rtdevice.h>
#define HWTIMER_DEV_NAME "timer0" /* 定时器名称 */
/* 定时器超时回调函数 */
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
rt_kprintf("tick is :%d !\n", rt_tick_get());
return 0;
}
static int hwtimer_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
rt_hwtimerval_t timeout_s; /* 定时器超时值 */
rt_device_t hw_dev = RT_NULL; /* 定时器设备句柄 */
rt_hwtimer_mode_t mode; /* 定时器模式 */
/* 查找定时器设备 */
hw_dev = rt_device_find(HWTIMER_DEV_NAME);
if (hw_dev == RT_NULL)
{
rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
return RT_ERROR;
}
/* 以读写方式打开设备 */
ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
if (ret != RT_EOK)
{
rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);
return ret;
}
/* 设置超时回调函数 */
rt_device_set_rx_indicate(hw_dev, timeout_cb);
/* 设置模式为周期性定时器 */
mode = HWTIMER_MODE_PERIOD;
ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
if (ret != RT_EOK)
{
rt_kprintf("set mode failed! ret is :%d\n", ret);
return ret;
}
/* 设置定时器超时值为5s并启动定时器 */
timeout_s.sec = 5; /* 秒 */
timeout_s.usec = 0; /* 微秒 */
if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
{
rt_kprintf("set timeout value failed\n");
return RT_ERROR;
}
/* 延时3500ms */
rt_thread_mdelay(3500);
/* 读取定时器当前值 */
rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample);

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* I2C 使
* i2c_io_sample
* i2c_io_sample
* 使I2C总线设备i2c0
* I2C 1
*/
#include <rtthread.h>
#include <rtdevice.h>
#define I2C_BUS_NAME "i2c0" /* I2C总线设备名称 */
#define SLAVE_ADDR 0x2D /* 从机地址 */
#define STR_LEN 16 /* 接收发送的数据长度 */
static void i2c_io_sample(int argc, char *argv[])
{
struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
struct rt_i2c_msg temp_msg; /* I2C消息 */
rt_uint8_t buffer[STR_LEN] = { 0U };
rt_uint32_t i,num_msg;
rt_size_t s_stat;
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C_BUS_NAME); /* 通过名字获取I2C总线设备的句柄 */
if( i2c_bus == RT_NULL)
{
rt_kprintf("can't find i2c device :%s !\n",I2C_BUS_NAME);
return;
}
/*初始化消息*/
temp_msg.addr = SLAVE_ADDR; /* 从机地址 */
temp_msg.len = STR_LEN; /* 传输的数据长度 */
temp_msg.buf = buffer; /* 读写缓存器 */
num_msg = 1; /* 传输一条消息 */
temp_msg.flags = RT_I2C_RD; /* I2C读 */
s_stat = rt_i2c_transfer(i2c_bus,&temp_msg,num_msg); /* 传输消息 */
rt_thread_mdelay(400);
if( s_stat == num_msg )
{
rt_kprintf("receive successful. \n receive messege : %s \n:",buffer);
for( i = 0 ; i < STR_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
}
else
{
rt_kprintf("device s% recieve fail \n buffer : s%\n",I2C_BUS_NAME,buffer);
return;
}
for( i = 0 ; i < STR_LEN ; i++)
buffer[i]++;
temp_msg.flags = RT_I2C_WR; /* I2C写 */
s_stat = rt_i2c_transfer(i2c_bus,&temp_msg,num_msg); /* 传输一条 */
rt_thread_mdelay(400);
if( s_stat == num_msg )
{
rt_kprintf(" send successful \n messege : %s \n:",buffer);
for( i = 0 ; i < STR_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
}
else
{
rt_kprintf("device s% send fail \n",I2C_BUS_NAME);
return;
}
return;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(i2c_io_sample, i2c io sample);

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-09-25 misonyo first edition.
*/
/*
* PIN脚控制LED亮灭的使用例程
* led_sample
* led_sample 41
* 使PIN脚编号使
* led线程线1000ms改变PIN脚状态led灯
*
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <stdlib.h>
/* PIN脚编号查看驱动文件drv_gpio.c确定 */
#define LED_PIN_NUM 19 /*PF1*/
static int pin_num;
static void led_entry(void *parameter)
{
int count = 0;
/* 设置PIN脚模式为输出 */
rt_pin_mode(pin_num, PIN_MODE_OUTPUT);
while (1)
{
count++;
rt_kprintf("thread run count : %d\r\n", count);
/* 拉低PIN脚 */
rt_pin_write(pin_num, PIN_LOW);
rt_kprintf("led on!\r\n");
/* 延时1000ms */
rt_thread_mdelay(1000);
/* 拉高PIN脚 */
rt_pin_write(pin_num, PIN_HIGH);
rt_kprintf("led off!\r\n");
rt_thread_mdelay(1000);
}
}
static int led_sample(int argc, char *argv[])
{
rt_thread_t tid;
rt_err_t ret = RT_EOK;
/* 判断命令行参数是否给定了PIN脚编号 */
if (argc == 2)
{
pin_num = atoi(argv[1]);
}
else
{
pin_num = LED_PIN_NUM;
}
tid = rt_thread_create("led",
led_entry,
RT_NULL,
512,
RT_THREAD_PRIORITY_MAX / 3,
20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(led_sample, led sample);

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* PIN 使
* pin_beep_sample
* pin_beep_sample
*
*/
#include <rtthread.h>
#include <rtdevice.h>
/* 引脚编号通过查看驱动文件drv_gpio.c确定 */
#ifndef BEEP_PIN_NUM
#define BEEP_PIN_NUM 19 /* PF1 */
#endif
#ifndef KEY0_PIN_NUM
#define KEY0_PIN_NUM 52 /* PC11 */
#endif
#ifndef KEY1_PIN_NUM
#define KEY1_PIN_NUM 53 /* PC12 */
#endif
void beep_on(void *args)
{
rt_kprintf("turn on beep!\n");
rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
}
void beep_off(void *args)
{
rt_kprintf("turn off beep!\n");
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
}
static void pin_beep_sample(void)
{
/* 蜂鸣器引脚为输出模式 */
rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
/* 默认低电平 */
rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
/* 按键0引脚为输入模式 */
rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为beep_on */
rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);
/* 按键1引脚为输入模式 */
rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为beep_off */
rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE);
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pin_beep_sample, pin beep sample);

View File

@ -0,0 +1,189 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* pm睡眠唤醒的使用例程
* pm_sample
* pm_sample
*
*
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_pm.h"
#define PM_NAME "pm" /* 设备名称 */
#define WAKE_UP_PIN 51 /* 唤醒源 */
#define SLEEP_TIMES 12 /* 进入睡眠次数,轮流进入不同的睡眠模式,包括无睡眠模式 */
struct pm_callback_t
{
volatile int in_fun_times; /*进入函数的次数*/
volatile char flag; /*标志*/
volatile int mode; /*需要打印的模式*/
};
volatile struct pm_callback_t g_pm_data;
uint32_t save_load_mem[1024] __attribute__ ((aligned(4))); /*备份的空间*/
/*进入睡眠前,睡眠唤醒后,都会进入。*/
/*函数打印睡眠相关的信息*/
void sleep_in_out_callback(rt_uint8_t event, rt_uint8_t mode, void *data)
{
/*没有标志,不处理*/
if(!(g_pm_data.flag))
{
return;
}
/*标志不正常,清空标志*/
if((g_pm_data.flag) > 2)
{
(g_pm_data.flag) = 0;
return;
}
/*模式不匹配*/
if(g_pm_data.mode != mode )
{
return;
}
/*进入的事件*/
switch(event)
{
/*进入睡眠前*/
case RT_PM_ENTER_SLEEP: g_pm_data.flag = 1;
rt_kprintf("\n\r##%d : ENTER ",g_pm_data.in_fun_times);
save_register(UART0,sizeof(UART_TypeDef),save_load_mem); /*备份寄存器的值*/
g_pm_data.in_fun_times++; /*进入睡眠次数+1*/
break;
/*睡眠唤醒后*/
case RT_PM_EXIT_SLEEP: g_pm_data.flag = 0; /*睡眠唤醒后*/
load_register(UART0,sizeof(UART_TypeDef),save_load_mem); /*还原寄存器的值*/
rt_kprintf("\n\rEXIT\n\r");
rt_pm_release(mode); /*释放休眠模式*/
return;
default: break;
};
/*当前的睡眠模式*/
switch(mode)
{
case PM_SLEEP_MODE_NONE: rt_kprintf("PM_SLEEP_MODE_NONE\n\r");
break;
case PM_SLEEP_MODE_IDLE: rt_kprintf("PM_SLEEP_MODE_IDLE\n\r");
break;
case PM_SLEEP_MODE_LIGHT: rt_kprintf("PM_SLEEP_MODE_LIGHT\n\r");
break;
case PM_SLEEP_MODE_DEEP: rt_kprintf("PM_SLEEP_MODE_DEEP\n\r");
break;
case PM_SLEEP_MODE_STANDBY: rt_kprintf("PM_SLEEP_MODE_STANDBY\n\r");
break;
case PM_SLEEP_MODE_SHUTDOWN: rt_kprintf("PM_SLEEP_MODE_SHUTDOWN\n\r");
break;
case PM_SLEEP_MODE_MAX: rt_kprintf("PM_SLEEP_MODE_MAX\n\r");
break;
default: break;
}
}
/* pm测试函数 */
static void pm_test(void *parameter)
{
int in_mode[7],i = 0;
g_pm_data.in_fun_times = 0;
g_pm_data.flag = 0;
in_mode[0] = PM_SLEEP_MODE_NONE;
in_mode[1] = PM_SLEEP_MODE_IDLE;
in_mode[2] = PM_SLEEP_MODE_LIGHT;
in_mode[3] = PM_SLEEP_MODE_DEEP;
in_mode[4] = PM_SLEEP_MODE_STANDBY;
in_mode[5] = PM_SLEEP_MODE_SHUTDOWN;
in_mode[6] = PM_SLEEP_MODE_MAX;
/*设置回调函数和私有数据*/
rt_pm_notify_set(sleep_in_out_callback,RT_NULL);
while(i < SLEEP_TIMES)
{
g_pm_data.mode = in_mode[i%6];
/*无休眠模式,不赋予标志*/
if(g_pm_data.mode != PM_SLEEP_MODE_NONE)
{
g_pm_data.flag = 2;
}
/*请求选择的休眠模式*/
rt_pm_request(in_mode[i%6]);
rt_thread_mdelay(500);
/*无休眠模式,不需要额外的等待*/
while(( g_pm_data.flag != 0 )&&(g_pm_data.mode != PM_SLEEP_MODE_NONE))
{
rt_thread_mdelay(500);
}
/*释放选择的休眠模式*/
rt_pm_release(in_mode[i%6]);
i++;
}
/*清除回调函数和私有数据*/
rt_pm_notify_set(RT_NULL,RT_NULL);
rt_kprintf("thread pm_test close\n\r");
}
/*按键唤醒的回调函数*/
void wake_by_pin(void *args)
{
}
static int pm_sample(int argc, char *argv[])
{
rt_thread_t thread;
/* 按键引脚为输入模式 */
rt_pin_mode(WAKE_UP_PIN, PIN_MODE_INPUT_PULLUP);
/* 绑定中断下降沿模式回调函数名为wake_by_pin */
rt_pin_attach_irq(WAKE_UP_PIN, PIN_IRQ_MODE_RISING, wake_by_pin, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(WAKE_UP_PIN, PIN_IRQ_ENABLE);
thread = rt_thread_create("pm_test", pm_test, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create pm_test thread failed!\n\r");
}
return RT_EOK;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pm_sample, pm sample);

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-25 misonyo first implementation.
*/
/*
* PWM 使
* pwm_led_sample
* pwm_led_sample
* PWM LED LED不停的由暗变到亮
*/
#include <rtthread.h>
#include <rtdevice.h>
#define LED_PIN_NUM 19 /* PF1 LED PIN脚编号查看驱动文件drv_gpio.c确定 */
#define PWM_DEV_NAME "pwm1" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 2 /* PA1 PWM通道 */
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
static int pwm_led_sample(int argc, char *argv[])
{
rt_uint32_t period, pulse, dir;
period = 500000; /* 周期为0.5ms单位为纳秒ns */
dir = 1; /* PWM脉冲宽度值的增减方向 */
pulse = 0; /* PWM脉冲宽度值单位为纳秒ns */
/* 查找设备 */
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
if (pwm_dev == RT_NULL)
{
rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);
return RT_ERROR;
}
/* 设置PWM周期和脉冲宽度默认值 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
/* 使能设备 */
rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
while (1)
{
rt_thread_mdelay(50);
if (dir)
{
pulse += 5000; /* 从0值开始每次增加5000ns */
}
else
{
pulse -= 5000; /* 从最大值开始每次减少5000ns */
}
if (pulse >= period)
{
dir = 0;
}
if (0 == pulse)
{
dir = 1;
}
/* 设置PWM周期和脉冲宽度 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pwm_led_sample, pwm sample);

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-30 misonyo first implementation.
*/
/*
* RTC 使
* rtc_sample
* rtc_sample
* RTC设备的日期和时间
*/
#include <rtthread.h>
#include <rtdevice.h>
static int rtc_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
time_t now;
/* 设置日期 */
ret = set_date(2018, 12, 3);
if (ret != RT_EOK)
{
rt_kprintf("set RTC date failed\n");
return ret;
}
/* 设置时间 */
ret = set_time(11, 15, 50);
if (ret != RT_EOK)
{
rt_kprintf("set RTC time failed\n");
return ret;
}
/* 延时3秒 */
rt_thread_mdelay(3000);
/* 获取时间 */
now = time(RT_NULL);
rt_kprintf("%s\n", ctime(&now));
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(rtc_sample, rtc sample);

View File

@ -0,0 +1,152 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy first implementation.
*/
/*
* SPI 使
* spi_io_sample
* spi_io_sample
* SPI设备先读取数据1
*/
#include <rtthread.h>
#include <rtdevice.h>
#define SPI_DEVICE_NAME "spi00"
#define BUF_LEN 16
static void spi_io_sample(int argc, char *argv[])
{
struct rt_spi_device * spi_dev; /* spi设备的句柄 */
struct rt_spi_configuration spi_config;
rt_uint8_t i,buffer[BUF_LEN] = { 0U };
rt_err_t s_stat;
rt_err_t result;
/* 查找 spi设备 获取spi设备句柄 */
spi_dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
if (spi_dev == RT_NULL)
{
rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_DEVICE_NAME);
return;
}
/* 清空配置结构体 */
rt_memset(&spi_config,0,sizeof(struct rt_spi_configuration));
spi_config.mode &= ~RT_SPI_SLAVE; /* 主机模式 */
spi_config.mode &= ~RT_SPI_3WIRE; /* 4线双向传输 */
spi_config.mode |= RT_SPI_CPHA; /* 第二边沿采样 */
spi_config.mode |= RT_SPI_CPOL; /* 空闲高电平 */
spi_config.mode |= RT_SPI_NO_CS; /* 禁用软件从机选择管理 */
spi_config.mode |= RT_SPI_MSB; /* 高位在前 */
spi_config.data_width = 8; /* 数据长度8 */
spi_config.max_hz = 2000000; /* 最快时钟频率 */
/* 配置SPI设备 */
s_stat = rt_spi_configure(spi_dev,&spi_config);
if(s_stat != RT_EOK)
{
rt_kprintf(" spi config fail !\n ");
return;
}
/* 获取总线 ,防止总线被多个线程同时使用 */
result = rt_spi_take_bus(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s take spi bus failed! \n", SPI_DEVICE_NAME);
return;
}
/* 选中片选 */
result = rt_spi_take(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s take spi cs failed! \n", SPI_DEVICE_NAME);
return;
}
/*接收一次数据*/
result = rt_spi_recv(spi_dev,buffer,BUF_LEN);
if(result != BUF_LEN)
{
rt_kprintf("receive fail. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
return;
}
rt_kprintf("receive successful. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
/* 将接收到的数据加1 */
for( i = 0 ; i < BUF_LEN ; i++)
buffer[i]++;
/*发送数据*/
result = rt_spi_send(spi_dev,buffer,BUF_LEN);
if(result != BUF_LEN)
{
rt_kprintf("send fail. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
return;
}
rt_kprintf("send successful. \n buffer is : %s \n:",buffer);
for( i = 0 ; i < BUF_LEN ; i++)
rt_kprintf(" %x",(unsigned int)buffer[i]);
rt_kprintf("\n");
/* 释放片选 */
result = rt_spi_release(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s release spi cs failed! \n", SPI_DEVICE_NAME);
return;
}
/* 释放总线 */
result = rt_spi_release_bus(spi_dev);
if (result != RT_EOK)
{
rt_kprintf(" %s release spi bus failed! \n", SPI_DEVICE_NAME);
return;
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(spi_io_sample, spi sample);

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* 使
* uart_sample
* uart_sample uart2
* 使使
* "hello RT-Thread!"
*/
#include <rtthread.h>
#define SAMPLE_UART_NAME "uart0" /* 串口设备名称 */
/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial;
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
/* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial_thread_entry(void *parameter)
{
char ch;
while (1)
{
/* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
/* 阻塞等待接收信号量,等到信号量后再次读取数据 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/* 读取到的数据通过串口错位输出 */
ch = ch + 1;
rt_device_write(serial, 0, &ch, 1);
}
}
static int uart_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
char uart_name[RT_NAME_MAX];
char str[] = "hello RT-Thread!\r\n";
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
/* 查找串口设备 */
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return RT_ERROR;
}
/* 初始化信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以中断接收及轮询发送方式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial, uart_input);
/* 发送字符串 */
rt_device_write(serial, 0, str, (sizeof(str) - 1));
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_sample, uart device sample);

View File

@ -0,0 +1,273 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-12-15 liuhy the first version
*/
#include "drv_pm.h"
#ifdef RT_USING_PM
//uint32_t save_mem[1024] __attribute__ ((aligned(4)));
void save_register(void *p_head,uint32_t size,void *p_save)
{
memcpy(p_save,p_head,size);
}
void load_register(void *p_head,uint32_t size,void *p_load)
{
uint32_t tmp;
memcpy(p_head,p_load,size);
if((p_head == UART0) || (p_head == UART1) || (p_head == UART2) ||
(p_head == UART3) || (p_head == UART4) || (p_head == UART5) )
{
tmp = ((UART_TypeDef*)p_load)->IVS;
((UART_TypeDef*)p_head)->IER = tmp;
}
}
static void uart_console_reconfig(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CONFIG, &config);
}
static void delay(void)
{
long i;
rt_base_t level;
level = rt_hw_interrupt_disable();
i = 0;
do{
i++;
}
while (i < 4000000);
rt_hw_interrupt_enable(level);
}
/**
* This function will put ES32F369x into sleep mode.
*
* @param pm pointer to power manage structure
*/
struct pm_callback_t
{
volatile int in_fun_times; /*进入函数的次数*/
volatile char flag; /*标志*/
volatile int mode; /*需要打印的模式*/
};
extern volatile struct pm_callback_t g_pm_data;
static void sleep(struct rt_pm *pm, uint8_t mode)
{
switch (mode)
{
case PM_SLEEP_MODE_NONE:
break;
case PM_SLEEP_MODE_IDLE:
break;
case PM_SLEEP_MODE_LIGHT:
/* Enter SLEEP Mode, Main regulator is ON */
ald_pmu_stop1_enter();
delay();
break;
case PM_SLEEP_MODE_DEEP:
/* Enter STOP 2 mode */
ald_pmu_stop2_enter();
delay();
break;
case PM_SLEEP_MODE_STANDBY:
/* Enter STANDBY mode */
ald_pmu_stop2_enter();
delay();
break;
case PM_SLEEP_MODE_SHUTDOWN:
/* Enter SHUTDOWNN mode */
ald_pmu_stop2_enter();
delay();
break;
default:
RT_ASSERT(0);
break;
}
}
static uint8_t run_speed[PM_RUN_MODE_MAX][2] =
{
{48, 0},
{48, 1},
{24, 2},
{2, 3},
};
static void run(struct rt_pm *pm, uint8_t mode)
{
static uint8_t last_mode;
static char *run_str[] = PM_RUN_MODE_NAMES;
extern uint32_t __system_clock;
if (mode == last_mode)
return;
last_mode = mode;
ald_cmu_clock_config_default();
__system_clock = 24000000;
switch (mode)
{
case PM_RUN_MODE_HIGH_SPEED:
case PM_RUN_MODE_NORMAL_SPEED:
/* hosc 12MHz, from hosc/3 pll to 48MHz */
ald_cmu_pll1_config(CMU_PLL1_INPUT_HRC_6, CMU_PLL1_OUTPUT_48M);
/* MCLK 48MHz */
ald_cmu_clock_config(CMU_CLOCK_PLL1, 48000000);
break;
case PM_RUN_MODE_MEDIUM_SPEED:
break;
case PM_RUN_MODE_LOW_SPEED:
ald_cmu_clock_config(CMU_CLOCK_HRC, 2000000);
break;
default:
break;
}
/* 4. 更新外设时钟 */
uart_console_reconfig();
/* Re-Configure the Systick time */
SysTick_Config(ald_cmu_get_sys_clock() / RT_TICK_PER_SECOND);
rt_kprintf("switch to %s mode, frequency = %d MHz\n", run_str[mode], run_speed[mode][0]);
}
/**
* This function caculate the PM tick from OS tick
*
* @param tick OS tick
*
* @return the PM tick
*/
static rt_tick_t es32f3_pm_tick_from_os_tick(rt_tick_t tick)
{
rt_uint32_t freq = 1;
return (freq * tick / RT_TICK_PER_SECOND);
}
/**
* This function caculate the OS tick from PM tick
*
* @param tick PM tick
*
* @return the OS tick
*/
static rt_tick_t es32f3_os_tick_from_pm_tick(rt_uint32_t tick)
{
static rt_uint32_t os_tick_remain = 0;
rt_uint32_t ret, freq;
freq = 1;
ret = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
os_tick_remain += (tick * RT_TICK_PER_SECOND);
os_tick_remain %= freq;
return ret;
}
/**
* This function start the timer of pm
*
* @param pm Pointer to power manage structure
* @param timeout How many OS Ticks that MCU can sleep
*/
static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
{
RT_ASSERT(pm != RT_NULL);
RT_ASSERT(timeout > 0);
if (timeout != RT_TICK_MAX)
{
/* Convert OS Tick to pmtimer timeout value */
timeout = es32f3_pm_tick_from_os_tick(timeout);
/* MAX 0xFFFF */
if (timeout > 0xFFFF)
{
timeout = 0xFFFF;
}
}
}
/**
* This function stop the timer of pm
*
* @param pm Pointer to power manage structure
*/
static void pm_timer_stop(struct rt_pm *pm)
{
RT_ASSERT(pm != RT_NULL);
}
/**
* This function calculate how many OS Ticks that MCU have suspended
*
* @param pm Pointer to power manage structure
*
* @return OS Ticks
*/
static rt_tick_t pm_timer_get_tick(struct rt_pm *pm)
{
rt_uint32_t timer_tick;
RT_ASSERT(pm != RT_NULL);
timer_tick = 1;
return es32f3_os_tick_from_pm_tick(timer_tick);
}
/**
* This function initialize the power manager
*/
int drv_pm_hw_init(void)
{
static const struct rt_pm_ops _ops =
{
sleep,
run,
pm_timer_start,
pm_timer_stop,
pm_timer_get_tick
};
rt_uint8_t timer_mask = 0;
/* initialize timer mask */
timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
/* initialize system pm module */
rt_system_pm_init(&_ops, timer_mask, RT_NULL);
return 0;
}
INIT_BOARD_EXPORT(drv_pm_hw_init);
#endif

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-01 wangyq the first version
*/
#ifndef DRV_PM_H__
#define DRV_PM_H__
#include <rthw.h>
#include <board.h>
#include <rtdevice.h>
#include <ald_cmu.h>
#include <ald_pmu.h>
#include "shell.h"
int rt_hw_pm_init(void);
extern void save_register(void *p_head,uint32_t size,void *p_save);
extern void load_register(void *p_head,uint32_t size,void *p_load);
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB