準備工作
安裝 RT-Thread Studio。
建立 Nano 工程
打開 IDE,點選【檔案】-【建立】-【RT-Thread 項目】:

進入建立工程的配置向導:
注:可以通過修改 board.c 的
SystemClock_Config()
更改系統時鐘。
工程建立完畢,連接配接硬體,可直接進行編譯下載下傳,如下所示:
編寫main.c
将以下代碼直接拷貝至main.c
/*
* 2019-09-09 RT-Thread
*/
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
/* PLEASE DEFINE the LED0 pin for your board, such as: PA5 */
#define LED0_PIN GET_PIN(C, 13)
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
/* 線程1的入口函數 */
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1)
{
/* 線程1采用低優先級運作,一直列印計數值 */
rt_kprintf("thread1 count: %d\n", count ++);
rt_thread_mdelay(500);
}
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 線程2入口 */
static void thread2_entry(void *param)
{
int count = 1;
/* set LED0 pin mode to output */
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
while (count++)
{
/* set LED0 pin level to high or low */
rt_pin_write(LED0_PIN, count % 2);
LOG_D("Hello RT-Thread!");
rt_thread_mdelay(100);
}
// rt_uint32_t count = 0;
//
// /* 線程2擁有較高的優先級,以搶占線程1而獲得執行 */
// for (count = 0; count < 10 ; count++)
// {
// /* 線程2列印計數值 */
// rt_kprintf("thread2 count: %d\n", count);
// rt_thread_mdelay(500);
// }
// rt_kprintf("thread2 exit\n");
// /* 線程2運作結束後也将自動被系統删除
// (線程控制塊和線程棧依然在idle線程中釋放) */
}
/* 删除線程示例的初始化 */
int thread_sample(void)
{
/* 建立線程1,名稱是thread1,入口是thread1_entry*/
tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY-1, THREAD_TIMESLICE);
/* 如果獲得線程控制塊,啟動這個線程 */
if (tid1 != RT_NULL)
{
//啟動線程
rt_thread_startup(tid1);
}
/* 初始化線程2,名稱是thread2,入口是thread2_entry */
rt_thread_init(&thread2,
"thread2",
thread2_entry,
RT_NULL,
&thread2_stack[0],
sizeof(thread2_stack),
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
//啟動線程
rt_thread_startup(&thread2);
return 0;
}
int main(void)
{
thread_sample();
return RT_EOK;
}
運作結果
在建立工程向導中配置了控制台序列槽号及其引腳号,是以工程中已經實作了 uart 的驅動以及
rt_hw_console_output()
,預設可以進行列印。打開序列槽終端,可以發現在終端中執行了列印。
RT-Thread Studio 結合 STM32CubeMx 開發其他外設驅動
使用
RT-Thread Studio
建立 RT-Thread 的項目時直接就将 RT-Thread 實時作業系統移植到對應的晶片上了,省去了系統移植的步驟。
使用
STM32CubeMx
配置工具可以友善快速的配置晶片外設的時鐘和引腳,使驅動的開發變得簡單。
是以本文将結合這兩個 IDE 的優點,介紹基于
RT-Thread Studio
和
STM32CubeMx
的驅動開發。
需要注意的是這裡開發的驅動是不基于 RT-Thread 裝置驅動架構的,即直接使用
STM32CubeMx
生成的 HAL 庫檔案來開發外設驅動。
簡介
使用
RT-Thread Studio
和
STM32CubeMx
開發驅動可分為以下幾個步驟
- 使用
建立 RT-Thread 工程RT-Thread Studio
- 使用
配置外設和系統時鐘STM32CubeMx
- 複制
函數stm32xxxx_hal_msp.c
- 修改
檔案,打開相應外設支援。stm32xxxx_hal_config.h
- 替換
檔案中時鐘配置函數board.c
- 使用外設
建立 RT-Thread 項目
使用
RT-Thread Studio
建立基于
nano-v3.1.3
的工程,界面如下圖所示
配置過程可總結為以下步驟:
- 定義自己的工程名及工程生成檔案的存放路徑
- 選擇
建立工程,選擇的 RT-Thread 版本為基于晶片
。nano-v3.1.3
- 選擇廠商及晶片型号
- 配置序列槽資訊
- 配置調試器資訊
工程配置完成後點選下方的
完成
按鈕即可建立 RT-Thread 的工程。
基于 Studio 建立 RT-Thread 工程後,就可以基于建立的工程開發自己的驅動。下面将以
stm32l475-atk-pandora
開發闆為例,講解如何開發 ADC 驅動。
配置外設
建立基于目标闆卡的
CubeMx
工程,并配置自己需要使用的外設。
例如,示例開發闆的 PC2 連接配接的是 ADC1 的通道 3,使用
CubeMx
生成 ADC 的驅動代碼的配置結果如下所示:
複制
stm32xxxx_hal_msp.c
函數
将
CubeMx
生成的代碼
stm32l4xx_hal_msp.c
函數複制到 RT-Thread Studio 生成的工程中,并參與工程編譯。複制完成後的結果如下圖所示
由于我們并沒有使用 CubeMx 生成的工程,是以這裡需要将
stm32l4xx_hal_msp.c
檔案中
#include "main.h"
替換為
#include "board.h"
。
打開 HAL 庫配置檔案對應外設的支援宏
這裡我們使用了 ADC 外設,是以需要在
stm32l4xx_hal_config.h
檔案中将 ADC 子產品使能,取消 ADC 子產品的注釋即可,示例代碼如下
#define HAL_ADC_MODULE_ENABLED
修改系統時鐘(可選)
使用 RT-Thread Studio 建立 RT-Thread 工程時預設使用的是系統内部時鐘 HSI,這裡需要根據自己的闆卡配置将
STM32CubeMx
生成的時鐘配置函數拷貝到 RT-hread 的工程中。步驟如下
- 使用 CubeMx 配置自己闆卡的系統時鐘,并生成代碼
- 複制 CubeMx 工程中
檔案的main.c
系統時鐘初始化函數void SystemClock_Config(void)
- 替換
生成的工程中的RT-Thread Studio
檔案中的系統時鐘配置函數drv_clk.c
,如下圖所示。void system_clock_config(int target_freq_mhz)
- 如果使用外部時鐘,則需要更新工程中的
中的對應的外部時鐘頻率的值,以 HSE 為例,需要修改下面的時鐘頻率為實際使用的值:stm32xxxx_hal_conf.h
#define HSE_VALUE ((uint32_t)8000000U) /!< Value of the External oscillator in Hz /
使用外設
上述檔案配置完成之後,ADC 外設就可以使用的,在
main.c
中添加外設的使用代碼
ADC 外設的使用示例代碼如下
#include <rtthread.h>
#include "board.h"
ADC_HandleTypeDef hadc1;
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
rt_uint32_t get_adc_value(void)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
return (rt_uint32_t)HAL_ADC_GetValue(&hadc1);
}
int main(void)
{
int count = 1;
rt_uint32_t read_value = 0;
MX_ADC1_Init();
while (count++)
{
read_value = get_adc_value();
rt_thread_mdelay(1000);
rt_kprintf("adc value = %d\r\n", read_value);
}
return RT_EOK;
}
編譯下載下傳工程,将開發闆的 PC2 引腳連接配接到開發闆上的地,終端列印資訊如下
将開發闆的 PC2 引腳連接配接到開發闆的 3.3V 引腳,終端列印資訊如下
從上面兩個實驗列印結果可以看出我們成功使用了 ADC 外設。
注意事項
-
檔案中的系統時鐘配置函數需要根據自己的闆卡進行修改board.c
-
函數中主要完成的是外設引腳和時鐘的初始化,是以在使用stm32xxxx_hal_msp.c
生成外設的配置代碼時不能選擇為每個外設都生成CubeMx
檔案.c/.h
- 使用
外設時隻需要配置實際使用的外設,如果CubeMx
檔案和stm32xxxx_hal_msp.c
檔案或者drv_uart.c
檔案外設的初始化函數重定義,需要删除drv_spi.c
檔案中外設的初始化函數。stm32xxxx_hal_msp.c
參考連結:
https://www.cnblogs.com/pathfinder-world/p/14672508.html
https://www.rt-thread.org/document/site/tutorial/nano/nano-port-studio/an0047-nano-port-studio/
https://www.rt-thread.org/document/site/rtthread-studio/drivers/cubemx/rtthread-studio-cubemx/