芯查查logo
  • 数据服务
    1. 新产品
    2. 物料选型
    3. 查替代
    4. 丝印反查
    5. 查品牌
    6. PCN/PDN
    7. 查方案
    8. 查代理
    9. 数据合作
  • SaaS/方案
      SaaS产品
    1. 供应链波动监控
    2. 半导体产业链地图
    3. BOM管理
    4. 解决方案
    5. 汽车电子
    6. 政府机构
    7. 数据API
  • 商城
  • 行业资讯
    1. 资讯
    2. 直播
  • 论坛社区
    1. 论坛
    2. 学习
    3. 测评中心
    4. 活动中心
    5. 积分商城
  • 查一下
  • 开通会员
搞机佬
创作者认证
基于STM32f103c8t6标准库的RT-thread移植

整体介绍:

使用的单片机型号为stm32f103c8t6,之所以选择这款芯片还是因为其小巧玲珑,之后做一些小的项目时,使用比较方便,另外这款芯片也是大部分人入门学习的一款。

编译器使用的是keil5。

RT-thread 官方网站:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/an0038-nano-introduction

移植前准备工作:

①   首先得有一份stm32f103c8t6的裸机程序,最简单的即可,如点灯。。。

②   在keil5编译环境下需要下载RT-thread 的nano pack包,可以直接在keil5软件内进行安装也可以离线下载后直接进行安装。这里推荐第二种,在keil5里面进行安装时下载速度一般都比较慢。

Nano pack包文末附的资源里面有。也可以自行下载:https://www.rt-thread.org/download/mdk/RealThread.RT-Thread.3.1.5.pack。

下载完成直接双击打开,全部保持默认一步一步往下走即可。

移植步骤:

①   首先打开准备好的裸机程序,添加nano pack软件包。

勾选之后点击“OK”就完成了nano pack包的添加。这样RT-thread的文件就添加到我们的工程当中了。

②   更改时钟与中断初始化

RT-thread操作系统会接管裸机程序当中原有的系统时钟与中断的初始化,所以我们要将裸机程序原有的系统时钟与中断的初始化屏蔽掉,然后在RT-thread的配置初始化文件当中去添加新的初始化函数。

首先要屏蔽掉原有的异常处理函数void SysTick_Handler(void)和悬挂处理函数void PendSV_Handler(void)

2、在board.c文件的void rt_hw_board_init(void)函数当中注释掉如下代码,并且添加

SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

 如下图所示:

删除完成之后添加如下函数:

void SysTick_Handler()
{
  rt_interrupt_enter();
  rt_tick_increase();
  rt_interrupt_leave();
}

并且在board.c文件顶部添加

#include “stm32f10x.h”

至此RT-thread核心的文件就全部移植完成。

此时如果编译有警告,请忽略,添加完后面的代码这个警告就自己消失了。

在主函数当中写一个线程实现led灯的闪烁。

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include <rtthread.h>
 
/*******************************************************************************
* 函 数 名         : main
* 函数功能                  : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
 
void thread01_entry(void *param);
static rt_thread_t thread01 = RT_NULL;
 
int main()
{
LED_Init();
thread01 = rt_thread_create("thrad01", thread01_entry, RT_NULL, 512, 3, 20);
rt_thread_startup(thread01);
}
 
void thread01_entry(void *param)
{
while(1)
{
           LED1 = 0;
           rt_kprintf("hello \n");
           rt_thread_mdelay(500);
           LED1 = 1;
           rt_thread_mdelay(500);
}
}

③   添加Finsh组件,实现串口打印以及命令输入。

本人觉得RT-thread的Finsh是非常便捷的一种串口调试方式,在后期调式代码时可以提供非常便捷的方式。

实现串口初始化,下面是基于标准库的串口初始函数:

#include "usart.h"              
#include <rtthread.h>
 
//int fputc(int ch,FILE *p)  //函数默认的,在使用printf函数时自动调用
//{
//       USART_SendData(USART1,(u8)ch);
//       while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
//       return ch;
//}
 
////串口1中断服务程序
////注意,读取USARTx->SR能避免莫名其妙的错误          
//u8 USART1_RX_BUF[USART1_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
////接收状态
////bit15,        接收完成标志
////bit14,        接收到0x0d
////bit13~0,    接收到的有效字节数目
//u16 USART1_RX_STA=0;       //接收状态标记
 
 
/*******************************************************************************
* 函 数 名         : USART1_Init
* 函数功能                  : USART1初始化函数
* 输    入         : bound:波特率
* 输    出         : 无
*******************************************************************************/
int USART1_Init(void)
{
   //GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
//NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
 

/*  配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX                          //串口输出PA9
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;      //复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);  /* 初始化串口输入IO */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX                     //串口输入PA10
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;                  //模拟输入
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */

 
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = 115200;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1

USART_Cmd(USART1, ENABLE);  //使能串口1

USART_ClearFlag(USART1, USART_FLAG_TC);
          
//       USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
 
//       //Usart1 NVIC 配置
//       NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
//       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
//       NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;             //子优先级3
//       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                     //IRQ通道使能
//       NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、      

return 0;
}
 
///*******************************************************************************
//* 函 数 名         : USART1_IRQHandler
//* 函数功能               : USART1中断函数
//* 输    入         : 无
//* 输    出         : 无
//*******************************************************************************/
//void USART1_IRQHandler(void)                    //串口1中断服务程序
//{
//       u8 r;
//       if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
//       {
//                 r =USART_ReceiveData(USART1);//(USART1->DR);         //读取接收到的数据
//                 if((USART1_RX_STA&0x8000)==0)//接收未完成
//                 {
//                          if(USART1_RX_STA&0x4000)//接收到了0x0d
//                          {
//                                   if(r!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
//                                   else USART1_RX_STA|=0x8000;      //接收完成了
//                          }
//                          else //还没收到0X0D
//                          {       
//                                   if(r==0x0d)USART1_RX_STA|=0x4000;
//                                   else
//                                   {
//                                             USART1_RX_BUF[USART1_RX_STA&0X3FFF]=r;
//                                             USART1_RX_STA++;
//                                             if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收  
//                                   }                 
//                          }
//                 }              
//       }
//}

 

#ifndef _usart_H
#define _usart_H
 
#include "system.h"
#include "stdio.h"
 
//#define USART1_REC_LEN              200         //定义最大接收字节数 200
 
//extern u8  USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
//extern u16 USART1_RX_STA;                         //接收状态标记
int USART1_Init(void);
 
#endif

打开rtconfig.h文件当中的这个宏定义,并且删除board.c文件当中的这个两个报错。

修改board.c当中的串口初始化代码如下:

static int uart_init(void)
{
           USART1_Init();
    return 0;
}
INIT_BOARD_EXPORT(uart_init);
 
void rt_hw_console_output(const char *str)
{
    rt_enter_critical();
 
    /* 直到字符串结束 */
    while ( *str != '\0' )
    {
        /* 换行 */
        //RT-Thread 系统中已有的打印均以 \n 结尾,而并非 \r\n,所以在字符输出时,需要在输出 \n 之前输出 \r,完成回车与换行,否则系统打印出来的信息将只有换行
        if ( *str == '\n' )
        {
            USART_SendData(USART1, '\r' );
            while ( USART_GetFlagStatus( USART1, USART_FLAG_TXE ) == RESET );
        }
 
        USART_SendData( USART1, *str++ );
        while ( USART_GetFlagStatus( USART1, USART_FLAG_TXE ) == RESET );
    }
 
    /* 退出临界段 */
    rt_exit_critical();
 
}

​

 添加Finsh源码:

​编辑

​编辑

 

这是编译有错误,点击错误进入文件,或者直接打开文件finsh_port.c并且替换文件的代码如下:

/*

 * Copyright (c) 2006-2021, RT-Thread Development Team

 *

 * SPDX-License-Identifier: Apache-2.0

 *

 * Change Logs:

 * Date           Author       Notes

 */



#include <rthw.h>

#include <rtconfig.h>

#include "system.h"



#ifndef RT_USING_FINSH

#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h

#endif



#ifdef RT_USING_FINSH



RT_WEAK char rt_hw_console_getchar(void)

{

/* Note: the initial value of ch must < 0 */

    int ch = -1;



  //查询方式实现,记得将Usart1初始化中的中断接收配置相关代码注释掉

    /*等待串口1输入数据*/

    if( USART_GetFlagStatus(USART1, USART_FLAG_RXNE ) != RESET )

    {

        ch = ( int )USART_ReceiveData( USART1 );

        USART_ClearFlag( USART1, USART_FLAG_RXNE );

    }

    else

    {

        if( USART_GetFlagStatus( USART1, USART_FLAG_ORE ) != RESET )

        {

            USART_ClearFlag( USART1, USART_FLAG_ORE );

        }

        rt_thread_mdelay( 10 );

    }

    return ch;

}



#endif /* RT_USING_FINSH */

至此就全部移植完成。

烧录后串口打印信息如下:

​编辑

​

工程附件
stm32f103c8t6移植rt-thread.zip
STM32C8T6核心板
版块: 单片机/MCU论坛
2024/06/17 21:12
  • 举报
😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷😸😹😺😻😼😽😾😿🙀🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏✂✅✈✉✊✋✌✏✒✔✖✨✳✴❄❇❌❎❓❔❕❗❤➕➖➗➡➰🚀🚃🚄🚅🚇🚉🚌🚏🚑🚒🚓🚕🚗🚙🚚🚢🚤🚥🚧🚨🚩🚪🚫🚬🚭🚲🚶🚹🚺🚻🚼🚽🚾🛀Ⓜ🅰🅱🅾🅿🆎🆑🆒🆓🆔🆕
@好友

全部评论

加载中
游客登录通知
已选择 0 人
自定义圈子
移动
发布帖子
发布动态
发布问答
最新帖子
萤火工场GD32VW553-IOT测评+蓝牙串口透传树莓派pico 2测评 - 初体验【工程师经验】+ 飞线【开源】zvs142857 2.1A,3A快充 充电宝迷你UC3842 开关电源优化全解析:攻克常见难题,提升性能
热门版块
查看更多
电子元器件
每日打卡
电子DIY
丝印反查
汽车电子工程师论坛
工业电子专区
新手入门指南
单片机/MCU论坛
PCB设计
开源项目

179

收藏

分享

微信扫码
分享给好友

评论