RT-thread的STM32f103c8t6移植

整体介绍:

使用的单片机型号为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的配置初始化文件当中去添加新的初始化函数。

1、首先要屏蔽掉原有的异常处理函数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 */

至此就全部移植完成。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞机佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值