第二篇: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、源码下载链接:

点此下载

原文地址:https://www.cnblogs.com/fdjy-no1/p/9812751.html

时间: 2024-10-10 08:30:42

第二篇:STM32F103C8T6移植Rt_thread(内置 oled、双串口、shell、AM2302,print 等驱动)的相关文章

Python之路(第二十六篇) 面向对象进阶:内置方法

一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常) class Foo: ? def __init__(self,x): self.x = x ? def __getattr__(self, item): print("执行__getattr__") ?

Python之路(第二十七篇) 面向对象进阶:内置方法、描述符

一.__call__ 对象后面加括号,触发执行类下面的__call__方法. 创建对象时,对象 = 类名() :而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() class Foo: ? def __call__(self, *args, **kwargs): print("我执行啦") ? f = Foo() f() #对象加括号调用执行类下的__call__方法 #输出结果 我执行啦 二.__next__和__iter__实现迭代器协议 迭

Python学习之旅 —— 基础篇(四)内置函数、装饰器

本篇要点: 内置函数 装饰器 一.内置函数 # abs() :取绝对值 >>> res = abs(-10) >>> print(res) 10 # 0,None,"",{},[],() 布尔值都为空 # all(),any() 判断值的真假 # all() 所有为真才为真 p = all([0,1,2,3]) # 0为False,所有p 是False print(p) # any() 任意一个为真即为真 p = any((0,""

函数篇 ---&gt; 装饰器与内置函数

装饰器: 从名字上来看,装饰器就是用来装饰内容的一个工具.本质上是一个闭包 在开发中,装饰器必须要遵守开放封闭原则:对扩展开放,对修改源代码封闭. 在装饰器中,有一个很重要的工具就是@,称之为语法糖,语法糖的本质就是:被装饰的函数名 = 装饰器的名字(被装饰的函数名) 在装饰器的应用上,有一个很简单的例子 计算简易的函数运行时间 import time # 导入time模块 print(time.time()) # 获取时间戳 start_time = time.time() # 开始时间 de

第二周(2)——内置函数

                                                              内置函数 abs()√ all() any() ascii() bin() bool() bytearry() bytes() callable() chr() compile() complex() dict() dir() enumerate() help() id() isinstance() float() format() frozenset() globals(

JSPx详细篇——其他一些JSP内置对象

pageContext对象 获取页面上下文的pageContext()对象是一个比较特殊的对象,通过它可以获取JSP 页面的request.response.session.application.exception等对象.pageContext()对象的创建和初始化是由容器来完成的.JSP页面中可以直接使用pageContext()对象. 1.pageContext对象获取会话范围 pageContext对象的常用方法: forward(java.lang.String URL):把页面转发到

[Modern PHP] 第二章 新特性之七 内置HTTP服务器

内置HTTP服务器 你知道PHP从5.4.0开始有了一个内置的web服务器吗?对于那些只知道使用Apache或者nginx去预览PHP页面的PHP开发者们来说这又是一块未被发掘的宝石.虽然你不能在产品环境中使用PHP的内置web服务器,但是这个功能对于本地开发来说真是的一个完美的工具. 无论我是否在写PHP代码,反正每天都会使用PHP的内置web服务器.我会使用它来预览Laravel和Slim Framework(译者注:框架的作者就是本书的作者Josh Lockhart)应用程序,在使用Dru

【class】类的内置方法 双下划线开头和结尾的

 内置方法  说明  __init__(self,...)  初始化对象,在创建新对象时调用  __del__(self)  释放对象,在对象被删除之前调用  __new__(cls,*args,**kwd)  实例的生成操作  __str__(self)  在使用print语句时被调用  __getitem__(self,key)  获取序列的索引key对应的值,等价于seq[key]  __len__(self)  在调用内联函数len()时被调用  __cmp__(stc,dst)  比较

Flask初识,第六篇,Flask中内置的session

Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from flask import session app = Flask(__name__) app.secret_key = "DragonFire" secret_key 实际上是用来加密字符串的,如果在实例化的app中没有 secret_key 那么开启session一定会抛异常的 2.