第二篇:STM32F103C8T6移植Rt_thread(内置 oled、双串口、shell、AM2302,print 等驱动)
首先打个广告:如果需要做毕设以及嵌入式项目合作,欢迎进入我们工作室:创想嵌入式设计工作室
一边看《扶摇》,一边写博客 ,两不误。
最近在做一个嵌入式开发项目,需要用到双串口,出于实时性考虑,需要实时操作系统,同时基于成本和工作量的要求,最终 敲定的 方案时rt_thread+STM32F103C8T6,之前 从没有在STM32上移植过rt_thread,本想图省事,想着在网上 下载一个DEMO,改改直接用,可是 ,遗憾的是,网上关于移植rt_thread的文章不少 ,但都是浅尝辄止。更是没有居于STM32F103C8T6的移植,(可能是因为该单片机资源太少,不值得移植 ),单独我来说,由于其具有较高的性价比,而且最终实测STM32F103C8T6上跑rt_thread毫无 压力,甚至最终 我在该系统上移植了oled,print,shell,双串口等驱动。运行流畅,完全满足要求。具体移植后的全部工程源码也会分享出来,(下载链接见本博尾)
另外值得一提的时 ,既然 使用了 RTOS,那么shell是必备的组件组件,因为该组件在代码调试过程中简直太方便了。
同时本次移植还有 一个特色点就是把STM32F103C8T6的两个串口全部有效利用起来了,一个串口输出调试信息,一个 串口用于与其他MCU进行片上通信。
好了,闲话少说,开始移植:
1、准备软件
1、keil5_arm (必须为最新版本 ,否则 无法安装rt_thread库)
2、rt_thread安装库,本人使用的是rt-thread.rtthread.2.1.1.pack
3、串口调试助手、串口驱动
以上列举软件在我的第一篇博文中有详细的介绍,点此阅读。
2、keil5软件按照后如图所示:
3、安装rt-thread.rtthread.2.1.1.pack
将rt-thread.rtthread现在后放到KEIL5的按照路径下:F:\intiall\keil5\ARM\Pack。然后点击默认安装即可
安装中。。。
4、打开keil5软件,进行工程配置;
3、导入工程,建立初始化工程
添加到”board.c“中初始化信息
#include <rthw.h>
#include <rtthread.h>
#include "usart.h"
#include "delay.h"
#include "led.h"
#include <stm32f10x.h>
#ifdef __CC_ARM
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="HEAP"
#define HEAP_BEGIN (__segment_end("HEAP"))
#else
extern int __bss_end;
#define HEAP_BEGIN (&__bss_end)
#endif
#define SRAM_SIZE 20
#define SRAM_END (0x20000000 + SRAM_SIZE * 1024)
/**
* This function will initial STM32 board.
*/
void rt_hw_board_init()
{
// rtthread tick configuration
// 2. Configure rtos tick and interrupt
SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_console_set_device(RT_CONSOLE_DEVICE_UART);
rt_console_set_device(RT_CONSOLE_DEVICE_SHELL);//shell ±?D?·??ú×?oó£??2???°??μ?
#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
rt_system_heap_init((void*)HEAP_BEGIN, (void*)SRAM_END);
#endif
/*******************user***************************/
delay_init(72);
LED_Init();
rt_hw_usart_init();
/**************************************************/
}
// rtthread tick configuration
// 3. add tick interrupt handler
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
建立main函数:
#include "led.h"
#include "rtthread.h"
/************************************************
创想工作室 MiniSTM32开发板 RT-Thread实验18
特色组件shell - 库函数版本
RT-Thread官方微信公众号:RTThread
RT-Thread技术论坛:http://www.rt-thread.org
创想工作室官方微信公众号:创想工作室
创想工作室技术论坛:www.openedv.com
创想工作室淘宝店铺:http://eboard.taobao.com
作者: RT-Thread & 创想工作室
************************************************/
static struct rt_thread led0_thread;//线程控制块
static struct rt_thread led1_thread;//线程控制块
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_led0_thread_stack[1024];//线程栈
static rt_uint8_t rt_led1_thread_stack[1024];//线程栈
rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
extern struct stm32_uart uart2_device;
extern struct stm32_uart uart1_device;
//线程LED0
static void led0_thread_entry(void* parameter)
{
while (1)
{
LED0=0; //注意:F7不支持位带操作,LED操作请参考代码修改
rt_thread_delay(1000); //延时500个tick
LED0=1;
rt_thread_delay(1000); //延时500个tick
rt_kprintf("this task 1\n");
}
}
//线程LED1
static void led1_thread_entry(void* parameter)
{
while (1)
{
LED1=0;
rt_thread_delay(1000); //延时100个tick
LED1=1;
rt_thread_delay(1000); //延时100个tick
rt_kprintf("this task 2\n");
}
}
//#include "oled.h"
//#include "dht22.h"
//#include "KEY.h"
//#include "my_uart.h"
void user_code(void)
{
// OLED_Init(); //初始化OLED
// AM2302_init(); //开启AM2302线程,循环读取数据。
// KEY_Init();
// my_uart_init();
}
int main(void)
{
// 创建静态线程
rt_thread_init(&led0_thread, //线程控制块
"led0", //线程名字,在shell里面可以看到
led0_thread_entry, //线程入口函数
RT_NULL, //线程入口函数参数
&rt_led0_thread_stack[0], //线程栈起始地址
sizeof(rt_led0_thread_stack),//线程栈大小
3, //线程的优先级
20); //线程时间片
rt_thread_startup(&led0_thread); //启动线程led0_thread,开启调度
// 创建静态线程
rt_thread_init(&led1_thread, //线程控制块
"led1", //线程名字,在shell里面可以看到
led1_thread_entry, //线程入口函数
RT_NULL, //线程入口函数参数
&rt_led1_thread_stack[0], //线程栈起始地址
sizeof(rt_led1_thread_stack), //线程栈大小
3, //线程的优先级
20);
rt_thread_startup(&led1_thread); //启动线程led1_thread,开启调度
/* init user code */
user_code();
}
end:
5、源码下载链接: