完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 michael_llh 于 2016-8-10 17:10 编辑 MSP430教程之九 上次一讲中我们说到了定时器的两种写法,一种是利用寄存器进行书写的,另外一种是利用官方库函数进行书写的。我们通过对比这两种写法,发现库函数居然写的要比寄存器还多,这不是更加不方便了吗。其实库函数和寄存器应该说各有好处吧,因为ti官方给了我们很多的寄存器定义,所以相对看起来不是那么难懂,库函数的话也相对是简洁明了的。我个人的观点是,在一些相对寄存器较少,运行速度较慢的单片机里面我们用寄存器写的话是最高效的,对于430来说,官方给的库相对的话运行速度不会和寄存器差点哪去(具体我也没测试过,瞎说),但库函数一定会比操作寄存器慢一点,因为他需要多步才可以配置到寄存器。但是之后大家如果接触32的话也会发现同样存在寄存器和库函数的版本,也同样是这个道理,库函数慢一点,但是简洁明了,方便。寄存器更快,但是识别度相对会低一点。但对32的72MHz的运行速度也就基本没什么差了。讲了这么多想说明一个什么道理呢?我们现在接触的单片机是算很底层的操作了,很底层的设计和应用了,相对的,我们有ARM9等等,这些复杂的芯片,就已经没有办法用所谓的寄存器进行操作了,因为它拥有的寄存器实在是太多了,所以就会有系统的产生,让芯片运行在系统上面,底层的东西集成了,减少了开发难度。之后大家接触了其他语言,比如c++和java,其实这两个是类似的,只要会了一个另一个也基本花一点时间就可以学会了。这两个语言的思想也和这个类似,把很多东西封装起来,你只要懂得怎么调用就好了,和我们调用函数类似,不用考虑函数具体是怎么实现这个功能的。 所以希望大家既可以明白寄存器具体是怎么操作的,同时学会应用库函数进行开发。 这一次我们将进入一个重要的篇章,通信协议,这个我们会通过几个章节来讲,主要介绍下面三种通信协议,一种是串口UART,一种是SPI,一种是IIC,三种我们都讲通过实例来说明。 这次我们要说的是串口UART的使用,串口应该算是一种最简单的通信方式了,我们通常值得串口指的是UART-Lite,也就是说它是由四根线组成,分别是VCC,RX,TX,GND。我们常用的就是这四根线了,真正意义上他还有一些其他的功能的线我们也很少用到。 UART的全称是通用异步收发传输器,是属于一种串行的数据总线,我们解释一下什么事串行的吧,比如说我要穿一个八位的数据,0100_1100,这样子,那好我现在要给你这个数据,我就有两种方式,一种是串行,一种是并行的了。 从上面的串行方式,我们又可以引出另外一个东西,就是我们一位一位的传的话时间间隔的问题,如果我可以选择任意时间传一个数据,每个数据之间的时间间隔不同的话就是所谓的异步通信,如果以相同的时间间隔的话就是所谓的同步通信了。 好了,我们现在来了解一下串口通信中比较重要的几个参数: a.波特率: 简洁明了,就是你要传多快的问题。从上面我们看到是把一个字节拆分成成八个位,那么波特率指的就是说每秒钟传多少个位了,举个例子,比如说波特率为9600bps,那么就是1秒钟内传输9600个bit,就是1200个字节,应该可以明白吧。 b. 数据位 这个怎么说呢,我们看图好了。 一个数据包就由上面三个组成,也就是说,我们在使用UART通信的话就需要配置这三个参数,到了我们写程序的时候大家还会看到这三个参数。 c. 停止位 用于上面我们数据包中的最后一位,典型值为1位,1.5位,2位。该位提供了时钟的方式,如果双方时钟不同步,可以通过该位来调整时钟的同步。 d. 奇偶校验位 简单解释下奇偶校验位,就是统计我们这个数据当中给定位数的二进制数中的1的个数是奇数还是偶数个。是一种最简单的数据传输错误检测的方式了。 看到这里可能大家还是会有不明白的地方,但是没有关系,最简单的方法就是我们先用起来,什么参数,什么原理,都不管他,用的时候遇到什么问题在百度嘛!!! 好了,干起来!! 建立工程就不在说了。 同样打开我们的两份文档,数据手册和库函数参考手册。 同样看到这么多的函数,我们还是需要使用到初始化函数。但是这里我们看到它前面有一个EUSCI,不禁问道,这是什么鬼!!!通过看到数据手册我们知道全称是Enhanced Universal Serial Communication Interface,翻译过来就是增强通用串行通信接口,TI把UART和SPI以及IIC都归类在这里面,之后我们会讲到另外两个,同样也是串行通信的方式。 在这之前我们还有注意一点,一定需要配置时钟,因为默认的时钟相对不是那么准确,我们配置成我们想要的时钟频率这样子方便我们写程序和计算。 我们从官方给的注释中可以很快的得到我们的参数输入。 这里我也不再解释具体的写法了,我们就直接写了。 在数据手册的 我们找到下面的说明,就是我们上面说到的UART通信的几个要设置的元素之一,就是波特率的设置,这里因为是英文,看起来比较吃力,我们翻译过来。 波特率设置: 要计算出正确的设置给波特率的生成,执行以下步骤: 1.计算出 N = fBRCLK / Baudrate 如果N>16则调到步骤3,否则执行步骤2 2.设置UCOS16 = 0,UCBRx = INT(N) 之后执行步骤4,这里我解释一下, INT(N)这里指的是N的整数部分,等下我们会看到设置的部分计算出的N是会有小数的。 3.UCOS16 = 1,UCBRx = INT(N/16),UCBFRx = INT( [ N/16 - INT ( N/16 ) ] x 16) 4.UCBRSx 能够在Table21-4中找到,等下我们会用到。我们要运用我们运算得到N - (INT)N的小数部分,来对应表格找到UCBRSx该赋予的值。 5.如果UCOS16 = 0被选中了,建议进行详细的误差计算。 (图中的OS16指的就是UCOS16这个位) 好了我们看下具体的使用方法,比如我们要设置波特率为9600,那么该怎么做? 第一步: 我们需要选择一个fBRCLK,那么我们在UART模块的Block diagram中找到, 我们可以看到它有三个时钟进行选择,分别是UC0CLK、ACLK、SMCLK,通过配置UCSSELx这个寄存器可以得到。后面两个时钟相信大家都比较熟悉了,那我们看一下第一个时钟是什么。(翻遍了数据手册没有找个的说明,可能我找到的不够仔细,翻了几本书也没有找到,但是后面我们也基本没有用到这个,暂且忽略吧,等我明白了是什么,会在补充上来的) 这样我们的时钟也就选定了。假定我们选择ACLK,这里的ACLK是32.768KHz,从我们时钟图上面可以看出,这里不再说明哈,大家试着自己找一下咯!! 我们就可以计算出N值了,N = fBRCLK / Baudrate = 3.4133333 第二步: 这里我们要选择OS16这个位为1或者0 我们先选择为0,即进入了MSP430的UART的低频率控制模式,那么我们需要跳转到第四步去执行,我们需要查阅Table21-4,如下: 这里我们需要先计算一下我们的UCBRx = INT(N/16) = 0 N - (INT)N = 3.413 - 3 = 0.413,对应表格如下: 所以这里我们要设置UCBRSx = 0x53。 同样的如果我们设置OS16这个位为1,即进入了MSP430的UART的过采样模式,那么我们就要执行上面的第3步了。 UCBRx = INT(N/16) = 0 UCBFRx = INT( [ N/16 - INT ( N/16 ) ] x 16) = 0 通过上面我们大概了解了整个波特率的设置过程,我们会发现这中间其实非常的复杂和繁琐,也有很多东西我们设置完了就根本不知道对不对,我自己看的时候也是搞得很晕,一看就觉得烦导致这一讲的教程写了一个礼拜都没写完就是一直拖拖拖,但是我们认真的去看数据手册的话在后面可以看到其实TI给了我们相关的推荐配置,我们可以按照官方给的配置进行相关的寄存器配置从而达到我们想要的效果。 这两幅图中就给出了所有时钟源的大小对应的波特率以及UCOS位的设置对应的一些寄存器的值,我们以后可以不用自己去计算那些量,可以直接运用查表的方式进行配置,这样可以更加方便,同时配置出来的相对比较可靠。 是不是觉得前面都是废话,其实也不然,这算是一个探索的过程吧,也能够帮助我们去明白这个过程是怎么实现的,如果觉得前面都是废话,那直接跳到这里来就好了。 我们选择配置这个参数,选择这个参数也有一定原因的,是因为我们看到后面的TX error和RX error的百分比都是比较低的,所以他的通信可靠性比较高,所以我们选择这个进行配置。 好了接下来看下我们的库函数代码: 写完了才发现,板子上没有把P2.0 P2.1这两个口引出来,坑!!教训!!! 后来想想不对,我们板子插进电脑的时候回有一个串口出现,应该我们的ESUCI_A0模块也就是我们对应P2.0和P2.1所对应的串口了。 好了我们现在写好了一下的代码: 相对注释的话也比较清楚了,有什么不明白的地方留言一下,我会帮你解答的。 这里解释一下:MSB/LSB (Least Significant Bit)/(Most Significant Bit) 这个的意思就是说,举个例子来说比较清楚,就是说我们要发一个自己的数据比如说我们发一个数据位0100_1011这样,那么我们看来这个数据从低位0到最高位1这样子,那么我们在发送这个数据的时候就有两种模式了,一种是LSB,就是从最低位开始发到最高位,也就是最低位有效,那么另外一种自然而然就是相反了,从高位往地位开始发到最低位,就是MSB模式了,这样子大家应该可以明白了吧。 这个部分还算是比较难的,很多东西需要细细去看,一步一步去做,像我调试这个程序的时候我一直以为是我的计算出错了,还是那个寄存器的配置出错了,但后来发现不是这样的,是因为的总中断没开,就这么一句简单的话,哎!!!弄了半天。 我们看下实际的效果,我们把代码下载进去,打开我们的软件,这里我用的是XCOM V2.0,的串口软件,如果你有其他的也可以。 串口选择如图所示: 这一讲花了很长时间,说实话没有一直在看这个部分,是因为他很复杂,一再看着看着就放弃了,要是以前可能就不想学了,就直接放弃了,但是现在是有责任在身必须要给大家一个好的交代,这一块可能讲的不是很好,后面我会在进行改进的。
|
|
相关推荐
|
|
感谢版主,前九章东西都有看,写得很好,大家共勉,一起学习!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
谢谢分享~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
|
|
写得生动,非常感谢.
把复杂的东西写得简单,明了.让人容易理解.是一件了不起的事. |
|
|
|
|
|
写得生动,非常感谢.
把复杂的东西写得简单,明了.让人容易理解.是一件了不起的事. |
|
|
|
|
|
谢谢支持,可能还有很多东西没有完善,细节的东西可能说的还不到位,这是第一版的文章,等整个系列更新完成之后我会在统一整理和修改的 |
|
|
|
|
|
向楼主请教一个问题,我的接受中断向量USCIAB0RX_VECTOR的触发条件是什么,为什么我单片机什么也没收到的时候就会跳进中断里
|
|
|
|
|
|
这个中断条件是有接收到数据,才会触发中断的,如果不是,可能哪里设置上面有改动,你再看下程序 |
|
|
|
|
|
|
|
|
|
|
|
uint8_t ReceiveData = 0;
void main(void) { // stop watchdog WDT_A_hold(WDT_A_BASE); PMM_unlockLPM5(); // 设置内部DCO频率为1MHz CS_setDCOFreq(CS_DCORSEL_0,CS_DCOFSEL_0); // 设置SMCLK时钟源来自DCO CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1); GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2,GPIO_PIN1,GPIO_SECONDARY_MODULE_FUNCTION); GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2,GPIO_PIN0,GPIO_SECONDARY_MODULE_FUNCTION); EUSCI_A_UART_initParam EUSCI_A_UART_initStucture = {0}; EUSCI_A_UART_initStucture.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK; EUSCI_A_UART_initStucture.clockPrescalar = 6; EUSCI_A_UART_initStucture.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION; EUSCI_A_UART_initStucture.firstModReg = 8; EUSCI_A_UART_initStucture.secondModReg = 0x20; EUSCI_A_UART_initStucture.parity = EUSCI_A_UART_NO_PARITY; EUSCI_A_UART_initStucture.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT; EUSCI_A_UART_initStucture.uartMode = EUSCI_A_UART_MODE; EUSCI_A_UART_init(EUSCI_A0_BASE,&EUSCI_A_UART_initStucture); EUSCI_A_UART_enable(EUSCI_A0_BASE); EUSCI_A_UART_enableInterrupt(EUSCI_A0_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT); _enable_interrupts(); while(1); } #pragma vector=USCI_A0_VECTOR __interrupt void UART_ISR(void) { ReceiveData = EUSCI_A_UART_receiveData(EUSCI_A0_BASE); EUSCI_A_UART_transmitData(EUSCI_A0_BASE,ReceiveData); } 我完美的打出来了,也完美的实现了功能,现在就差完美的理解啦,哈哈哈 |
|
|
|
|
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
3012个成员聚集在这个小组
加入小组2876 浏览 1 评论
MSP430FR5994 使用库函数 定时器触发AD问题请教
3406 浏览 2 评论
请问怎么把下面51单片机的代码改成msp430 g2 pocket的代码,还有改下时间变成30秒
2322 浏览 1 评论
4778 浏览 1 评论
2556 浏览 1 评论
1294浏览 3评论
MSP430FR5994 使用库函数 定时器触发AD问题请教
3407浏览 2评论
2886浏览 1评论
1450浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-9 09:36 , Processed in 1.464301 second(s), Total 83, Slave 74 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号