使用ARM I/O重定向的另一种方法:编译器重定向

简介:

在实际的开发中,我们对于uart的转串口使用往往是通过对stdio库中的fputc等函数进行重定向来进行实现,实现方法如下图:

我们的目的是高级和低级函数都不target-dependent,并使用系统I/O功能与硬件接口。然而,高级库函数通过调用低级函数来执行输入/输出,而这些低级函数又调用target-dependent的系统I/O功能。 对于这样的问题,有这些解决方案:

  • 避免使用高级库函数。
  • 重新定义低级库函数。
  • 重新定义系统 I/O 功能。

对于重新定义低级库函数系统I/O函数哪个是更好的解决方案,这取决于你的使用场景。例如,UART一次写入一个字符时,默认使用缓冲,所以重新定义一个没有缓冲的函数可能更适合UART。然而,在需要进行缓冲操作的地方,重新定义系统I/O函数可能会更合适。 

ARM编译器运行时,MicroLib通过低级函数来与硬件进行接口。它实现了一组简化的高级函数,因此不实现系统I/O函数。因此,在使用MicroLib的情况下,不能重新定义系统I/O函数。

为了解决这个问题,可以使用 ARM 编译器的 I/O 重定向的方法来实现在使用MicroLib的情况下,进行重定义系统I/O函数。

实验平台为自制stm32f103c8t6开发板,理论上可应用于所有ARM架构芯片。

实验操作:

1.打开keil软件,这里使用的版本是keil uVision V5.38.0.0版本,新建工程,选择f103c8,进入Manage Run-Time Environment页面

2.选择运行资源,如下图:

 

 3.点击确定进入工程,此时工程文件如图:

点击进入RTE_Device.h文件,点击编辑栏下方 后进入配置,打开USART1,开启RX和TX引脚。

 4.向源文件目录添加文件:

在User Code Template中选择STDIN和STDOUT,添加stdin_USART.c与stdout_USART.c文件。

 与修改RTE_Device.h相同,进入配置界面,将两个文件配置均设置为USART1与9600波特率

5.因为我们需要同时实现输入输出功能,因此我们需要对代码进行一些修改,修改如下:

//在stdin中

#include "retarget_stdin.h"
#include "Driver_USART.h"

//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------

// <h>STDIN USART Interface

//   <o>Connect to hardware via Driver_USART# <0-255>
//   <i>Select driver control block for USART interface
#define USART_DRV_NUM           1

//   <o>Baudrate
#define USART_BAUDRATE          9600

// </h>


#define _USART_Driver_(n)  Driver_USART##n
#define  USART_Driver_(n) _USART_Driver_(n)

extern ARM_DRIVER_USART  USART_Driver_(USART_DRV_NUM);
#define ptrUSART       (&USART_Driver_(USART_DRV_NUM))


/**
  Initialize stdin

  \return          0 on success, or -1 on error.
*/
int stdin_init (void) {
  int32_t status;

  status = ptrUSART->Initialize(NULL);
  if (status != ARM_DRIVER_OK) return (-1);

  status = ptrUSART->PowerControl(ARM_POWER_FULL);
  if (status != ARM_DRIVER_OK) return (-1);

  status = ptrUSART->Control(ARM_USART_MODE_ASYNCHRONOUS |
                             ARM_USART_DATA_BITS_8       |
                             ARM_USART_PARITY_NONE       |
                             ARM_USART_STOP_BITS_1       |
                             ARM_USART_FLOW_CONTROL_NONE,
                             USART_BAUDRATE);
  if (status != ARM_DRIVER_OK) return (-1);

  status = ptrUSART->Control(ARM_USART_CONTROL_RX, 1);
  if (status != ARM_DRIVER_OK) return (-1);
	
  status = ptrUSART->Control(ARM_USART_CONTROL_TX, 1);
  if (status != ARM_DRIVER_OK) return (-1);

  return (0);
}


/**
  Get a character from stdin

  \return     The next character from the input, or -1 on read error.
*/
int stdin_getchar (void) {
  uint8_t buf[1];

  if (ptrUSART->Receive(buf, 1) != ARM_DRIVER_OK) {
    return (-1);
  }
  while (ptrUSART->GetRxCount() != 1);
  return (buf[0]);
}

//在stdout中

#include "retarget_stdout.h"
#include "Driver_USART.h"

//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------

// <h>STDOUT USART Interface

//   <o>Connect to hardware via Driver_USART# <0-255>
//   <i>Select driver control block for USART interface
#define USART_DRV_NUM           1

//   <o>Baudrate
#define USART_BAUDRATE          9600

// </h>


#define _USART_Driver_(n)  Driver_USART##n
#define  USART_Driver_(n) _USART_Driver_(n)

extern ARM_DRIVER_USART  USART_Driver_(USART_DRV_NUM);
#define ptrUSART       (&USART_Driver_(USART_DRV_NUM))


/**
  Initialize stdout

  \return          0 on success, or -1 on error.
*/
//int stdout_init (void) {
//  int32_t status;

//  status = ptrUSART->Initialize(NULL);
//  if (status != ARM_DRIVER_OK) return (-1);

//  status = ptrUSART->PowerControl(ARM_POWER_FULL);
//  if (status != ARM_DRIVER_OK) return (-1);

//  status = ptrUSART->Control(ARM_USART_MODE_ASYNCHRONOUS |
//                             ARM_USART_DATA_BITS_8       |
//                             ARM_USART_PARITY_NONE       |
//                             ARM_USART_STOP_BITS_1       |
//                             ARM_USART_FLOW_CONTROL_NONE,
//                             USART_BAUDRATE);
//  if (status != ARM_DRIVER_OK) return (-1);

//  status = ptrUSART->Control(ARM_USART_CONTROL_TX, 1);
//  if (status != ARM_DRIVER_OK) return (-1);

//  return (0);
//}


/**
  Put a character to the stdout

  \param[in]   ch  Character to output
  \return          The character written, or -1 on write error.
*/
int stdout_putchar (int ch) {
  uint8_t buf[1];

  buf[0] = ch;
  if (ptrUSART->Send(buf, 1) != ARM_DRIVER_OK) {
    return (-1);
  }
  while (ptrUSART->GetTxCount() != 1);
  return (ch);
}

 6.添加main.c,进行io的输入输出测试

#include "stm32f10x.h"
#include "retarget_stdin.h"
#include "retarget_stdout.h"

void print(char str[])
{
	for (int o = 0; o <= sizeof(str); o++)
	{
		stdout_putchar(str[o]);
	}
}

int main(void)
{
	stdin_init();
	while(1)
	{
		int i = stdin_getchar();
		if(i == 1)
		{
			print("hello");
		}
	}
}

编译通过,烧录测试,结果如下,完毕

 

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值