【AT91SAM3S】英倍特串口示例工程05-UART中,串口是怎样初始化的
在这个示例工程的main.c文件中,进入main之后,没有发现串口功能的任何配置。直接使用了printf这个东西进行输出。将软件下载到开发板上之后,在电脑端使用串口软件,可以看板子有数据发来。说明这个虽然没有显式初始化的串口,确实已经被初始化好了。
跟踪可发现,uart的功能函数都在uart_console.c文件中实现。但是这些功能到底是在那里加入到主程序里边的,在什么时候执行的,我却没找到。这个问题困扰了我好久。
知道今天,再次看这个程序的时候才发现点眉目。
首先,要理解一个东西就是:printf的功能,是通过对函数fputc的重定义来实现的。
在这个工程中,fputc函数的实现是在retarget.c文件中实现的。具体代码是这样的:
int fputc(int ch, FILE *f)
{
if ((f == stdout) || (f == stderr))
{
UART_PutChar( ch ) ;
return ch ;
}
else
{
return EOF ;
}
}
即,调用了函数uart_console.c文件中UART_PutChar来发送字符串。
其次,找出来在哪里对串口进行初始化的。
MCU启动后,加载向量表,执行_Reset_Handler进入main函数。在main函数中,直接调用使用了串口功能的printf进行输出。这里看似没有对串口进行初始化。其实,这个例子里边对串口初始化使用了个很独特的放大即:用到的时候再初始化。如果整个工程都没有用到串口功能,这个串口初始化就不去进行。
首先printf调用了fputc完成其功能。而fputc的功能是由UART_PutChar实现的。
我们看看UART_PutChar这个函数,他的实现是这样的:
extern void UART_PutChar( uint8_t c )
{
Uart *pUart=CONSOLE_USART ;
if ( !_ucIsConsoleInitialized )
{
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
}
/* Wait for the transmitter to be ready */
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
/* Send character */
pUart->UART_THR=c ;
}
这里有一个变量ucIsConsoleInitialized,是一个全局变量。表示串口是否已经进行了初始化:ucIsConsoleInitialized为0时,说明串口还未完成初始化,其他值时说明串口已经完成初始化。
第一次使用串口时,串口没有初始化。在这里就会调用UART_Configure函数对串口进行初始化操作。之后就不再进行串口的初始化而是直接使用了。
总结以上步骤,UART的初始化调用过程是这样的:
Printf----fputc--- UART_PutChar--- UART_Configure。初始化完成。
那么,fputc是在什么时候加载到咱们写的程序中来的呢?
我们可以看到,在_Reset_Handler中有个跳转到__main()的语句,而我们写的入口函数是main()。在这里__main()是MDK库中提供的一个函数,在这里完成了库的加载。Fputc属于标准库的内容,因此我判断fputc是在这里加载到咱们写的程序中来的。
也就是说,进入main函数之前,printf功能已经完成了。进入main函数之后直接使用即可。第一次发送数据时,完成串口的初始化。
【AT91SAM3S】英倍特串口示例工程05-UART中,串口是怎样初始化的的更多相关文章
- 使用 VSCode 给STM32配置一个串口 printf 工程
使用 VSCode 给STM32配置一个串口 printf 工程 gcc 重定向 printf 和 keil 不一样. 文件准备 先从以前的工程中拷过一份串口的代码来,然后在 main 函数中初始化串 ...
- Spring示例工程
---------------siwuxie095 创建一个基于 Spring IoC 的小程序的步骤: 建立 Spring 工 ...
- activiti学习2:示例工程activiti-explorer.war的使用
目录 activiti学习2:示例工程activiti-explorer.war的使用 一.搭建开发环境 二.运行示例工程 三.示例工程功能演示 1. 创建流程图 2. 部署流程图 3. 启动流程 4 ...
- Vivado利用IP自带的示例工程和仿真
有时候想查看IP的特性和功能,又不想自己写testbench,Vivado自带的IP示例工程就能派上用场,原来一直不知道怎么打开IP的示例工程 第一步:在原有的工程中新建IP,按照你想要的IP属性,例 ...
- Android Jetpack Compose 引入示例工程
引入 Jetpack Compose 示例工程 去GitHub上找到Compose的示例工程 https://github.com/android/compose-samples ,clone到本地 ...
- 34.QT-制作串口助手(并动态检测在线串口,附带源码)
qextserialport-1.2rc库下载链接: http://www.pudn.com/Download/item/id/2298532.html 1.添加源码到工程 将qextserialpo ...
- C#中串口与Modem的通信
C#中串口与Modem的通信 2007-08-20 09:52643人阅读评论(8)收藏举报 最近一段时间,试验了串口的数据传输.在C#中,其实有一个很好的类SerialPort使串口间的通信变得简单 ...
- mini2440裸机试炼之——DMA直接存取 实现Uart(串口)通信
这个仅仅能作为自己初步了解MDA的开门篇 实现功能: 将字符串数据通过DMA0通道传递给UTXH0,然后在终端 显示.传输数据完后.DMA0产生中断,beep声, LED亮. DMA基本知识 计算机系 ...
- 转载 C#开发串口总结,并提炼串口辅助类到公用类库中
C#开发串口总结,并提炼串口辅助类到公用类库中 开发C#相关的项目有很多年了,一直没有接触串口的开发,近期由于工作的需要,需要了解熟悉对硬件串口的开发,通过对串口的深入了解,串口也不再是什么神秘的东西 ...
随机推荐
- mysql 关键字于数据库字段于关键字冲突的问题
如果数据库存储字段 为MySQL关键字,那么在查询或者其他操作时会出错.那么我们应该怎么办, 可能有些人会说,换个字段不就好了啊.当然这样也是可以的,完全没问题. 然而,如果是在无法对数据库进行修改和 ...
- dedecms最新版本修改任意管理员漏洞+getshell+exp
此漏洞无视gpc转义,过80sec注入防御. 补充下,不用担心后台找不到.这只是一个demo,都能修改任意数据库了,还怕拿不到SHELL? 起因是全局变量$GLOBALS可以被任意修改,随便看了下,漏 ...
- nodejs之process进程
虽然node对操作系统做了很多抽象的工作,但是你还是可以直接和他交互,比如和系统中已经存在的进程进行交互,创建工作子进程.node是一个用于事件循环的线程,但是你可以在这个事件循环之外创建其他的进程( ...
- [转]深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)
以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...
- user-select : 保护版权内容的简单方案
有的适合我们需要保护我们页面的内容,为了版权或者安全等原因,这个适合我们可以使用 user-select 这个CSS属性,简单易用. 嗯,这个属性不麻烦,而且也不是 CSS 3 / CSS 4 的新属 ...
- C#驱动及应用
一,使用开源客户端:StackExchange.Redis 二,使用方法: 1,获取访问redis数据库连接,代码如下. /// <summary> /// 获取访问redis数据 ...
- Client默认用户及登录密码(转)
Client默认用户及登录密码 SAP系统(如ERP.CRM等)安装完成,初始化状态下有若干个客户端(Client).如果是生产系统,一般只有000.001.066等三个Client:如果是IDES系 ...
- nopcommerce 初学2
好久没有接触nopcommerce了. 2016-9-5 现在最新的是3.8. 这段时间也稍微接触了下aspnet 的mvc. 所以就想到nop是一个开源的 很全得项目, 然后就拆了一些可以学习跟借 ...
- net 的单元测试 初学
1. 都要以一个方法 这样的去测试 2. 利用工具 Install-Package Moq -Version 4.0 (最高的是4.5 4.0适用于自己项目的版本) Moq.dll 进行测试 ...
- AsyncTask异步交互
package com.baidu.day06asynctask; import java.util.ArrayList; import java.util.List; import com.baid ...