您的位置 首页 电源

浅谈keil中库函数和寄存器联系

浅谈keil中库函数和寄存器关系-在一个芯片系统里,uart的驱动是厂商自己写好的,那他们是怎么关联printf到uart的呢?有人说,printf最终是调用了putchar,我搜索了源码,没有这个函数,估计是开发工具,像KeilC u3,里面已经集成了putchar。于是我奇怪,这个工具怎么知道厂商哪个函数时uart的,有没有命名规则要求?

评述:在一个芯片体系里,uart的驱动是厂商自己写好的,那他们是怎样相关printf到uart的呢?有人说,printf最终是调用了putchar,我查找了源码,没有这个函数,估量是开发东西,像KeilC u3,里边现已集成了putchar。所以我古怪,这个东西怎样知道厂商哪个函数时uart的,有没有命名规矩要求?如同没有,看了下面的评论,估量是经过UART的收发寄存器来相关的。我猜测应该是在某个当地,keilc相关了体系的寄存器列表,找到了串口的寄存器的地址,然后putchar操作该寄存器,就相当于操作了厂商或许开发者自界说的uart_write_byte.uart_read_byte.

所以在keilc里,他人写好的体系,能够直接调用printf输出。我觉得要弄了解,得研讨下keil是怎样处理库函数和寄存器的联络的。

关于putchar函数,估量printf是经过

便是在你装备完串口的时分首先写一个数到SBUF寄存器中然后在用printf函数打印就能够,当让这个次序是不能够变的,假如你想在诘问细节为什么,我只能告知你这应该是开发环境决议的,这一点我就了解这么多,假如有大侠给出更好的解说我也一同共勉。

其实也不必首先写一个数据到SBUF寄存器,只需在串口初始化后,加上一句TI=1;即可。原因是printf函数事实上是调用putchar输出字符的。之所以能输出到串口上,便是由于putchar函数把字符经过串口输出。
这是keil中putchar最简略的版别,其他版别也相同,看函数就了解为什么要先让TI=1;了,楼主写的那个SBUF=0,原理是相同的,写入了数据,那么TI就等于1了,然后就能够运用putchar函数和printf函数了。
putchar函数的源码在{keil装置目录下}\C51\LIB文件夹里的PUTCHAR.C文件里,另外在keil的协助文档里有阐明

char putchar (char c)  {

while (!TI);

TI = 0;

return (SBUF = c);

}

从下面这篇文章中,我如同找到答案了

评述:我在某个CortextM3的源码里的debug.c找到了fputc。应该说,某些体系是经过fputc树立联络,而不是putchar的。如下:

void fputc_hook(char ch)  

{  

if (DebugType == 0)  

{  

UARTWriteByte(ch, 1000);  

}  

else  

{  

VirtualUartWrite(ch);  

}  

}  

int fputc(int ch, FILE *f)  

{  

uint8 dgbBuffer[DEBUG_TIME_LEN];  

uint32 tmpcnt, i;  

if (ch == '\n')  

{          

tmpcnt = SysTickCounter;  

for (i = 0; i < DEBUG_TIME_LEN; i++)  

{  

dgbBuffer[i] = tmpcnt % 10;  

tmpcnt = tmpcnt / 10;  

}  

fputc_hook('\r');  

fputc_hook('\n');  

fputc_hook('[');  

for (i = 0; i < DEBUG_TIME_LEN; i++)  

{  

fputc_hook(dgbBuffer[DEBUG_TIME_LEN – 1 -i]+0x30);  

if (DEBUG_TIME_LEN – 1 -i == 2)  

{  

fputc_hook('.');  

}  

}  

fputc_hook(']');  

return OK;  

}  

fputc_hook(ch);  

return OK;  

}  

下面是参阅文章的转载:
 

在实践工作中,遇到了这么一个问题,需要向不同的串口传输ASCII码,无疑运用printf函数是最便利的。但是printf打印出的信息无法挑选出口。在网上搜到的程序,printf要调用fputc函数发送字符。该函数如下:


int fputc(int ch, FILE *f)
{
  /* e.g. write a character to the USART */
  USART_SendData(USART1, (uint8_t) ch);

  /* Loop until the end of transmission */
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
  {}

  return ch;
}

    进口参数有字符和字符要输出到的文件指针。依据查找,printf函数输出到stdout,而fprintf能够指定字符抵达的文件。可FILE结构体中,没有一个是与串口相关的。

typedef struct {
  char *fpos; /* Current position of file pointer (absolute address) */
  void *base; /* Pointer to the base of the file */
  unsigned short handle; /* File handle */
  short flags; /* Flags (see FileFlags) */
  short unget; /* 1-byte buffer for ungetc (b15=1 if non-empty) */
  unsigned long alloc; /* Number of currently allocated bytes for the file */
  unsigned short buffincrement; /* Number of bytes allocated at once */
} FILE;

    该怎么重定向呢?不知道。但有一个补偿的办法。
    自己界说n个FILE*指针,并恣意赋值。在fputc中使用if..else来做判别,代码如下:

FILE* FileUart1 = (FILE*)0x19;
FILE* FileUart2 = (FILE*)0x28;
int fputc(int ch, FILE *f) {
  if ( f == FileUart1 ) {
    USART_SendData(COM_USART[0], (uint8_t) ch);
    while (USART_GetFlagStatus(COM_USART[0], USART_FLAG_TC) == RESET){}
  }
  else if ( f == FileUart2 ) {
    USART_SendData(COM_USART[1], (uint8_t) ch);
    while (USART_GetFlagStatus(COM_USART[1], USART_FLAG_TC) == RESET){}
  }
}

    这样,fprintf(FileUart1,…)和fprintf(FileUart2,…)便能向不同的串口发送数据。哈哈,尽管没有真实做到重定向,仅仅用了个歪招,但开始的意图仍是达到了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/347496.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部