当前位置:  编程技术>移动开发
本页文章导读:
    ▪在单线程模型中Message、Handler、Message Queue、Looper其间的关系        在单线程模型中Message、Handler、Message Queue、Looper之间的关系。1. Android进程    当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默 认的情况下,所有该程序的组件都将.........
    ▪ 解读QML之4        解读QML之四                                         解读QML之四 QML对象属性         每一个QML对象类型都定义了一系列属性。每创建一个该对象类型的实例,该实例的这些属性也自动.........
    ▪ S5PV210学习札记——系统时钟和串口       S5PV210学习笔记——系统时钟和串口TQ210的系统时钟配置和串口配置非常简单,本文从TQ210的系统时钟配置开始讨论。 TQ210的时钟配置跟2440/6410的时钟配置差不多,只是锁相环的个数略有不同,.........

[1]在单线程模型中Message、Handler、Message Queue、Looper其间的关系
    来源: 互联网  发布时间: 2014-02-18
在单线程模型中Message、Handler、Message Queue、Looper之间的关系。

1. Android进程
   当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默 认的情况下,所有该程序的组件都将在该进程和线程中运行。

同 时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android 会尝试停止一些进程从而释放足够的资源给其他新的进程使用, 也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要 性,Android会首先停止那些不重要的进程。

按照重要性从高到低一共有五个级别:

前台进程
前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。一般来说, 在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。
可见进程
可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。
服务进程
运 行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用 户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。
后台进程
运 行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进 程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正 确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
空进程
未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓 存的平衡。
Android 对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服 务的进程重要级低。因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工 作,而不是开启一个子进程――特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片, 使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。
2. 单线程模型
    当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处 理。所以主线程通常又被叫做UI线程。在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
2.1 子线程更新UI
Android的UI是单线程(Single-threaded)的。为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。如果幕后的线程来 执行UI对象,Android就会发出错误讯息
CalledFromWrongThreadException。以后遇到这样的异常抛出时就要知道怎么回 事了!
2.2 Message Queue
     在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:
1. Message
    Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
2. Handler
    Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)
方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
3. Message Queue
    Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
    每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
4. Looper
    Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper() 得到当前线程的Looper就有可能为NULL。
    对于子线程使用Looper,API Doc提供了正确的使用方法:




    这个Message机制的大概流程:
    1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。
    2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用 该Message的target指向的Hander的dispatchMessage函数对Message进行处理。
    在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
    1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
    2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
    3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
    由此可见,我们实现的handleMessage方法是优先级最低的!
    3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!
    在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的 Looper对象是属于哪条线程的,则由该线程来执行!
    1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
    2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对 象


    
[2] 解读QML之4
    来源: 互联网  发布时间: 2014-02-18
解读QML之四
                                         解读QML之四 QML对象属性

        每一个QML对象类型都定义了一系列属性。每创建一个该对象类型的实例,该实例的这些属性也自动被创建了。接下来我们讨论几种不同类型的属性。

id属性

           每一个QML对象类型都有一个唯一确定的id属性。这个属性是由QML语言自身提供的,并且在QML对象类型中不能被重定义和重载。

        我们必须为id属性指定一个值允许该对象被唯一标示并且可用于被其它对象引用。Id属性值必须以小写字母或者下划线开始,只能包含字母,数字和下划线等字符。

        下面是一个TextInput对象和一个Text对象,TextInput对象的id属性值为”myTextInput”。Text对象的text属性值通过myTextInput.text被设置为和TextInput对象的text属性值一样。


         我们以后可以在该组件可见域内通过id属性引用该对象。因此id属性值在组件可见域内必须是唯一的。

         一旦对象实例被创建了,那么id属性值就不能被改变。Id属性看起来像普通属性,但是并非是真正的普通属性,我们对它应用特殊的语义,例如:在上面的例子中我们不能使用myTextInput.id。

property属性

        一个property是对象的一个属性,可以被赋为静态值或者是绑定到动态表达式上。一个property的值可以被其它的对象读取。一般情况下,property属性也可以被其它对象修改,除非该QML类型明确指定该property属性不能被修改。

 【定义property属性】

   一个property属性可以在C++中定义,并且通过Q_PROPERTY注册到QML类型系统。当然,我们也可以在QML文档中通过如下语法自定义对象的property属性:


         通过这种方式,一个对象可以将一些特定的值暴露给其它对象,或者是更加简便的维护一些内部状态。

         Property属性的名称必须以小写字母开头,且只能包含字母,数字和下划线。JavaScript的保留关键字不能作为property属性的名称。Default关键字是可选的,对于default以及default属性修改者的详细信息稍后讨论。

         定义一个自定义的property属性也就为该property属性隐式的创建了一个value-change信号,也就是关联了一个名为on<PropertyName>Changed的signal handler。<PropertyName>就是property属性的名称,而且首字母要大写。

         例如:下面就定义了两个property属性,并且实现了其signalhandler:


【自定义property属性的合法类型】

      QML基本类型中的枚举类型都可以作为自定义property属性类型。例如:下面都是合法的property属性声明:


        一些QtQuick模块提供的基本类型是不能作为property类型的,除非在QML文档中导入QtQuick模块。

       var基本类型是通用的类型,可以保存任意类型的值,包括lists和objects:


        另外,任何的QML对象类型都可以被用作property属性类型。例如:


        这对于自定义QML类型也是适用的。如果在ColorfulButton.qml文件中定义了一个QML类型,那么ColorfulButton类型的property属性也是合法的。

  【合法的property属性值】

我们可以通过两种方式为定义的property属性的值:

  *初始化

  *赋值

  值可以是静态值也可以是绑定表达式。

  {初始化}

    Property属性初始化:


     我们可以在定义property属性的时候,也进行初始化赋值:


       初始化赋值举例如下:


{赋值}

     我们可以使用JavaScript代码给property属性赋值,如下:


     举例如下:


【合法的property值】

     正如之前提到的,我们可以给property属性赋两类值:静态值和绑定表达式:


     示例:


        在许多情况下,string类型的值可以自动被转换为许多不同类型的值,因为QML提供了string类型到其它类型的转换(这也就是为什么你可以给color属性赋值”red”)。

         必须特别注意,绑定到一个表达式的情况下,右边的表达式必须的Qt.binding()函数的返回值,该函数返回合适的值类型。一个表达式可以在property属性初始化的时候直接赋值,而不需要使用那个函数(实际上使用函数还会导致错误)。

 【类型安全】

       属性都是类型安全的。给属性赋值必须是类型匹配的。

       例如,下面的赋值就会导致一个错误:


         如果在运行时的时候给属性赋类型错误的值,那么赋值也不会成功还会产生一个错误。

        正如在之前提到过的,一些属性类型并没有很好的类型来表达其值,这个时候QML引擎提供了很好的string类型转换。例如:color属性,该属性存储的值类型应该是color类型而不是string类型,但是你却可以给它指定string类型的值,而不会产生错误。

【特殊的property属性类型】

     对象列表类型的property属性

     List类型的property属性也可以被赋予QML对象类型列表的值。赋值的形式如下:


        例如:Item类型有一个状态属性,可以用于保存State对象类型的列表。下面的代码用于初始化该列表:


        如果列表仅仅包含一项,那么方括号可以省略:


        我们可以像下面这样定义对象列表类型的property属性:


      List类型的属性声明举例如下:


       如果你希望声明一个属性用于存储列表值,但不一定是存储QML对象类型值,这个时候你就需要声明var的property属性。

【分组的属性】

        在某些情况下,我们可以将属性根据逻辑分为子属性组。这些子属性可以通过”.”或者是组来赋值。

        例如:Text类型有一个font的组属性。在下面,第一个Text对象使用”.”初始化font的值,第二个则是使用组来赋值:


        组属性类型都是基本的类型。这些基本类型一部分是由QML语言提供的,另外一部分则是由Qt Quick模块提供的。

 【属性别名】

         属性别名就是保存对另一个属性的引用。不像普通属性的定义,普通属性的定义需要分配一个新的,唯一的存储空间,而一个属性别名仅仅是连接到了属性上。

         属性别名的定义根属性定义差不多,只是属性别名需要使用alias关键字代替属性定义中的property类型,右边的值必须是合法的引用别名:


        不像普通的属性,一个别名仅仅可以引用对象或者是对象的属性。

        例如:下面的Button类型有一个buttonText属性别名,链接到子Text对象的text属性:


       下面的代码会创建一个Button,并且定义文本字符串:


        修改了buttonText,就直接修改了textItem.text的值,它不会修改其它的值。如果buttonText不是属性别名,那么修改它的值是不会修改显示的文本的,因为属性绑定不是双向的。

【考虑属性别名】

     只有在组件完全初始化之后属性别名才会被激活。如果未初始化的别名被引用了就会产生错误。另外,为一个属性别名产生属性别名也会导致错误:


        我们可以为一个已经存在属性创建一个同名的属性别名,这就会覆盖已经存在的属性。例如:下面的QML类型有一个color属性别名,跟Rectangle内建的属性Rectangle::color属性:


【default属性】

         一个对象定义可以包含一个default属性。如果一个对象()子对象定义在另一个对象(父对象)之内而没有赋值给该父对象的任何属性,那么该子对象就是该父对象default属性的值。声明为default属性需要使用default关键字。

        例如下面的MyLabel.qml文件中的对象就有一个someText的默认属性:


       我们可以在MyLabel对象定义中为someText默认属性赋值:


        上面两个等同于下面一个:


       然而,由于someText属性被标记为默认属性,因此我们就没有必要显示的将Text对象赋值给这个默认属性。

       你也可能注意到了子对象可以添加到任何基于Item的类型,而不需要明确将它们添加到子属性上。这是因为Item的默认属性是data属性,任何添加到Item中的对象都自动添加到它的子对象列表。

        默认属性对于重新指定子对象是十分有用的。可以看看TabWidget示例,该示例就是使用默认属性自动重新指定TabWidget的子对象作为它的子对象列表。

 【只读属性】

   任何对象的定义都可以使用readonly关键字定义只读属性,使用下面的语法:


       只读属性必须在初始化的时候指定值。一旦只读属性被初始化了,它就不可能再被赋值了,无论是赋值(使用”=”)还是其它的方式。

       例如,下面的Component.onCompleted代码块就是非法的:


注意:一个只读的属性是不能声明为默认属性或者是属性别名的。

 【属性修改对象】

       属性可以有属性值修改对象与它们关联。我们可以像如下的这样定义属性修改对象实例,与特定的属性关联:


        需要注意的是,上面的语法实际上一个对象声明,将会实例化一个对象操作已存在的属性。

       特定的属性修改类型只能应用到特定的属性类型上,但是这并不是被语言强制的。例如:QtQuick模块提供的NumberAnimation类型仅仅影响数字类型(例如int或者real)属性。如果将NumberAnimation使用到非数字类型属性将不会引起错误,但是非数字属性将不会产生动画。属性修改类型的动作是与特定属性的实现紧密相关的。

 Signal属性

        信号就是当某些事件发生的时候从对象类型中发出通知:例如,一个属性改变,一个动画开始或者停止,或者当一个图片下载完成。例如,MouseArea类型当用户点击的时候就会发射一个点击信号。

        当一个信号发射了,对象可以通过signal handler被通知。一个signalhandler的定义语法为on<Signal>,<Signal>是信号的名称,首字母要大写。Signalhandler必须在发射该信号的对象定义的内部实现,并且signalhandler必须包括JavaScript代码块,当signal handler被调用的时候该代码块就会被执行。

         例如,MouseArea对象的定义中可以定义onClicked类型的signal handler,当MouseArea被点击了该signal handler就会被调用,使得控制台打印出消息:


【定义Signal属性】

        我们可以使用Q_SIGNAL在C++的类中定义Signal属性并注册到QML类型系统。可选的,我们也可以在QML文档中使用如下语法定义signal属性:


        在一个类型块中定义两个同名的信号或者方法将会产生错误。然而,我们可以使用已经存在的信号类型定义新的信号(这会导致之前的信号不可见)

       下面就是一个信号定义的示例:


         如果一个signal没有参数,那么”()”就是可选的。如果使用了参数,那么参数的类型就必须指定,例如上面的actionPerformed信号中的string和val参数。允许使用的参数类型根之前描述的定义property属性中的一样。

       要发射一个信号,那么就会调用一个方法。任何和信号关联的signal handler都会在信号被发射的时候执行,并且handlers可以使用定义的信号参数的名字和获取预期的参数。

【属性改变信号】

        QML类型也提供内建的属性改变信号,当属性值被改变的时候这些信号就会被发射。接下来我们就来介绍信号的好处以及如何使用。

【Signal Handler属性】

        Signal handlers是特殊的方法属性类型,当信号发射了,与信号关联的特定方法就会被调用。在QML中添加一个信号就会自动添加一个与之关联的signalhandler,默认情况下该函数就会是空实现。客户端可以提供自己的实现来实现程序逻辑:

       考虑下面的SquareButton类型,该类型是SquareButton.qml文件中定义的,定义了两个信号:activated和deactived:


        这些信号可以在同一目录下的其他QML文件中的任何SquareButton对象获取,客户端也提供了signalhandler实现:


【属性改变Signal Handler】

        属性改变的Signal handler语法如下on<Property>Changed,<Property>就是属性的名称,首字母要大写。例如,尽管TextInput类型文档没有定义textChanged信号,但是这个信号因为TextInput有一个text属性而可用。因此我们也就可以实现onTextChanged signal handler,当属性值被改变的时候就会调用该signal handler:


方法属性

           一个对象的方法就是在执行一些处理或者触发一些事件的时候被调用的。当一个方法连接到一个信号时,当信号被发射的时候,这些方法就会被执行。

【定义方法属性】

        我们可以通过在C++的类的函数使用Q_INVOKABLE注册到QML类型系统或者是在C++类中注册为Q_SLOT。可选的,我们也可以在QML文档中自定义方法添加到对象中:


       方法可以添加到QML类型以定义单独的可重用的JavaScript代码。这些方法可以在内部被调用或者是被外部对象调用。

       不像信号,这里不用定义参数的类型,因为它们默认为var类型。

        在同一个类型块中视图定义两个同名的方法或者是信号都会导致错误。然而,我们可以使用已存在的方法的名称定义新的方法(这会导致已存在的方法不可用)

        下面的Rectangle类型有一个calculateHeight()方法,当指定height值的时候该方法就会被调用。

         如果方法有参数,那么我们可以在方法中通过参数名访问它们。例如,MouseArea被点击,那么就会调用moveTo()方法,可以使用newX和newY设置文本的新位置:


附加属性和附加SignalHandler

        附加属性和附加的信号处理机制允许对象使用那些对象不可引用的外部属性和信号处理者。这允许对象访问那些与单个对象关联的属性和信号。

         一个QML类型实现可以选择创建附加的特定属性和信号。实例化这种类型就会在运行时创建,允许这些对象访问属性和信号。

引用附加的属性和handlers语法如下:


        例如:ListView类型有一个附加的属性ListView.isCurrentItem,该属性可以被ListView的每一个代理访问。该属性可以被每一个独立的代理对象来决定当前选择的是哪一个条目:


        在这种情况下,附加类型的名称是ListView和属性isCurrentItem,附加属性使用ListView.isCurrentItem引用。

        附加的signal handler也可以使用这种方式引用。例如:附加的signal handler是Component.isCompleted,当组件的创建过程完成后可以被用来执行一些JavaScript代码。在下面的示例中,一旦ListModel被完全创建,Component.onCompleted signal handler就会被自动执行:


         附加的类型名是Component以及completed信号,附加的signal handler可以这样引用:Component.isCompleted。

 【访问附加属性和Signal Handler的注意点】

        一个常见的错误是将设附加的属性和signal handler可以直接从子对象中访问。这并不是问题。附加类型的实例仅仅添加到特定的对象上,而不是对象以及其所有子对象之上。

       例如:下面的示例是之前的附加属性的改编版示例。在这次中,代理是一个Item,Rectangle就是该Item的子对象:


        这并不像预期中那样工作,因为ListView.isCurrentItem仅仅是附加到根代理对象,而不是它的子对象。由于Rectangle是代理的子对象,而不是代理本身,他不能使用ListView.isCurrentItem访问isCurrentItem附加属性。因此,rectangle必须通过根代理对象访问isCurrentItem属性:


         现在就可以通过 delegateItem.ListView.isCurrentItem正确引用到代理的isCurrentItem附加属性。

 


    
[3] S5PV210学习札记——系统时钟和串口
    来源: 互联网  发布时间: 2014-02-18
S5PV210学习笔记——系统时钟和串口

TQ210的系统时钟配置和串口配置非常简单,本文从TQ210的系统时钟配置开始讨论。

TQ210的时钟配置跟2440/6410的时钟配置差不多,只是锁相环的个数略有不同,配置步骤是一样的。配置系统时钟,无非要经过以下几个步骤:

(1)设置系统PLL锁定时间

(2)配置PLL

(3)配置各模块分频系数

(4)切换到PLL时钟

简单的看着四步似乎没有头绪,但是看到手册中的“S5PV210时钟生成线路图”就可以理解了,现在截图如下:


上图中无非就三种模块,PLL、MUX和DIV,MUX控制时钟源选择,PLL负责生成PLL时钟,DIV负责分频。

为了系统稳定,在设计电路时我们一般不会使用太高频率的晶振(避免高频线间/层间干扰),但是,S5PV210的内核需要的工作频率很高(最高可以达到1G),这中情况下,我们通常是通过锁相环(英文简称PLL)来对外部时钟源进行倍频,然后供内核使用(在TQ210开发板上采用的是12M晶振),因此,S5PV210提供了4个PLL(具体四个PLL的用途可以自己阅读手册),分别是APLL、MPLL、EPLL和VPLL,通过配置S5PV210提供的锁相环控制寄存可以设置锁相环的倍频系数,使内核工作频率达到800M或者1G。需要注意的是PLL设置完成之后并不能立刻稳定的工作,需要一个起振过程,在这段时间内PLL的输出频率很不稳定,因此,内核的工作也是很不稳定的,为了解决这个问题,S5PV210提供LOCK_TIME(锁定时间)模块(通过设置相应的LOCK_TIME寄存器可以设定锁定的时间长度),当锁相环控制寄存器的值发生改变时,系统会锁定内核,锁定内核时CPU不工作,此时锁定模块会根据LOCK_TIME设定的值进行计时,计时完成后CPU才会使用PLL提供的时钟信号工作。

默认状态下内核使用外部时钟源提供的时钟,配置好PLL后需要设置相应的MUX,使内核在PLL提供的时钟信号下工作。从上面的时钟生成线路图中还可以看到很多MUX,我们可以根据实际要求进行配置。注意,选通PLL的MUX应该在设置完分频之后配置。

内核可以工作在1G的时钟信号下,而其他设备工作频率较低,因此,需要根据实际要求进行分频,分频的值并不是随意的,应该根据手册上提供的参考值进行配置,以下是各模块的最高工作频率:


这样,配置完PLL和分频之后选通PLL,使CPU在高频模式下工作。

以上S5PV210的系统时钟配置逻辑,可能说了这么多您也很难理解,这时,您应该参考代码、手册和本文进行理解。S5PV210系统时钟配置的代码很多,这里我就不贴出来了,下面,我们讨论一下S5PV210的串口部分。

S5PV210的串口配置比起系统时钟来讲更为简单。学习串口应该先了解下串口的工作原理,认识一下串口,具体的工作原理可以阅读手册的串口部分,需要知道串口的相关配置参数,如波特率、数据位、停止位、校验位等,流控制相关的也可以看看,理解后自行配置一下,我们这里只讨论下串口的配置,为了简单起见,我们以非FIFO模式为例进行讨论。

直接阅读手册的寄存器控制部分,第一个寄存器便是ULCON。ULCON可以配置数据位长度、停止位长度、教研模式和红外模式,如果需要设置为8N1,非红外模式则可以将ULCON配置为0x3。

第二个寄存器是UCON,我们只配置一下传输/接收模式和时钟源即可,其他的采用默认方式,为了简单,我们选择“中断或查询模式”,以PCLK为时钟源,因此,可以配置UCON为0x5|(1<<10)。

我们使用非FIFO模式,可以不设置UFCON寄存器。

UMCON是流控制相关的,我们也不作配置。

接下来的四个STAT寄存器是表征串口工作状态的,无需配置。

接下来的UTXH是发送缓冲区寄存器和URXH是接收缓冲区寄存器。

UBRDIV和UDIVSLOT是配置串口波特率的,算法也比较简单,手册上提供了三个约束公式:

DIV_VAL = UBRDIVn + (num of 1's UDIVSLOTn)/16

DIV_VAL = (PCLK/(bps X 16))-1

或者

DIV_VAL = (SCLK_UART / (bps X 16)) - 1

我们选择PCLK作为串口工作时钟源,PCLK的频率为66.5M,如果我们要设置串口波特率为115200则可以如下计算:

DIV_VAL = (66.5 X 10^6 / (115200 X 16)) - 1 = 35.07,故UBRDIV应该设置为35,

另外,0.07*16 + 1 = 2,所以UDIVSLOT中应该有两个1,故可以设置为0x3,当然也可以是0x88等,只要有两个1位就可以。

到这里,串口就配置好了,还是比较简单的,您配置完后还可以自己配置下FIFO和流控制,学完中断和DMA之后还可以配置为中断或者DMA模式,这里就不多说了。代码比较简单,网上的例子也比较多,我就不上传了。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3