MSP430程序库<五>SPI同步串行通信

2019-10-10来源: eefocus关键字:MSP430  程序库  SPI  同步串行通信

SPI总线系统是一种同步串行外设接口;是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。 许多的芯片都用这种协议通信:EEPROM、Flash、实时时钟、AD转换器、数字信号处理器等:MSP430的USART模块不仅能够实现异步模式(见:MSP430程序库<二>UART异步串口),而且支持同步串行通信(即SPI模式);其SPI支持3线、4线操作,支持主机模式和从机模式,字符长度可以7位或8位等。由于要用AD7708芯片完成AD采样,AD7708是通过SPI与其它设备通信的;本程序比较简化,只完成了主机模式的初始化。


硬件介绍:

SPI:SPI是Motorola首先在其MC68HCXX系列处理器上定义的,它是一种同步的高速串行通信协议,有关SPI协议的详细内容,参考:SPI_互动百科。


MSP430对SPI的支持:当msp430USART模块控制器UxCTL的位SYNC置位时,USART模块工作于同步模式,对于149即工作于SPI模式,若是169,USART0可以支持I2C,可以通过另一控制位I2C控制,I2C位0则工作于SPI。在SPI模式下,允许单片机以确定的速率发送和接收7位或8位数据。


同步通信与异步通信类似;同步通信和异步通信寄存器资源一致,具体寄存器的不同位之间的功能存在差异;具体寄存器内容参见TI提供的用户指南。


USART模块的SPI操作可以是3线和4线,其信号如下: 

SIMO:从进主出,主机模式下,数据输出;从机模式下,数据输入。 

SOMI:从出主进,主机模式下,数据输入;从机模式下,数据输出。 

UCLK:USART SPI模式时钟,信号有主机输出,从机输入。 

STE:从机模式发送接收允许控制脚,用于4线模式,控制多主从系统中多个从机,避免发生冲突。具体方式如下(图截自 用户指南):

image

image四线主机模式:STE为高电平,SIMO和UCLK操作正常;STE为低电平,SIMO和UCLK被置为输入方向,主机控制权让出。 

四线从机模式:STE为高电平,从机的发送和接收无效,且把SOMI置为输入方向;STE为低电平,发送接收正常,SOMI也为正常输出。


USART模块串行时钟极性和相位设置:


USART的时钟UCLK的极性和相位由位于UxTCTL寄存器的CKPH和CKPL位控制,具体如下图:在程序中,我分别称之为,时钟模式0、时钟模式1、时钟模式2、时钟模式3。


image


USART的波特率产生,SPI不同于异步通信:异步通信由UxBR1UxBR0UxMCTL三个寄存器控制,以产生标准频率;而同步模式,主从设备用同一个时钟,不再需要产生标准时钟,故而不再用UxMCTL寄存器,设其值为0.


其他的,与异步通信基本一致,这里不再细说。具体参考用户指南。


程序实现:

程序和异步通信方式类似:首先是初始化函数,然后是读取数据、写入数据函数。此程序采用和我之前的UART程序库类似的结构,写入数据后进入低功耗等待中断,判断标志位进行写入数据和读取数据。


这里函数只实现430的主机模式,如需从机模式可以仿照我的程序,进行简化实现。


由于,我即将使用的SPI设备(AD7708)不是字符型设备,这里不再实现写入字符串函数,也不再移植printf和scanf函数,如若需要可以自己添加,printf和scanf的移植参考:MSP430程序库<四>printf和scanf函数移植


初始化函数:SpiMasterInit,实现主机模式的初始化工作,函数内容如下:


char SpiMasterInit(long baud,char dataBits,char mode,char clkMode)

{

    long int brclk;                 //波特率发生器时钟频率

    

    UxCTL |= SWRST;                 //初始

    

    //反馈选择位,为1,发送的数被自己接收,用于测试,正常使用时注释掉

    //UxCTL |= LISTEN;

    

    UxCTL |= SYNC + MM;             //SPI 主机模式

    

    //时钟源设置

    UxTCTL &=~ (SSEL0+SSEL1);       //清除之前的时钟设置

    if(baud<=16364)                 //

    {

      UxTCTL |= SSEL0;              //ACLK,降低功耗

      brclk = 32768;                //波特率发生器时钟频率=ACLK(32768)

    }

    else

    {

      UxTCTL |= SSEL1;              //SMCLK,保证速度

      brclk = 1000000;              //波特率发生器时钟频率=SMCLK(1MHz)

    }

    

    //------------------------设置波特率-------------------------   

    if(baud < 300||baud > 115200)   //波特率超出范围

    {

        return 0;

    }

    //设置波特率寄存器

    int fen = brclk / baud;         //分频系数

    if(fen<2)return (0);            //分频系数必须大于2

    else

    {

        UxBR0 = fen / 256;

        UxBR1 = fen % 256;

    }

    

    //------------------------设置数据位-------------------------    

    switch(dataBits)

    {

        case 7:case'7': UxCTL &=~ CHAR; break;      //7位数据

        case 8:case'8': UxCTL |= CHAR;  break;      //8位数据

        default :       return(0);                  //参数错误

    } 

    //------------------------设置模式---------------------------    

    switch(mode)

    {

        case 3:case'3': UxTCTL |= STC;  USPI3ON;    break;  //三线模式

        case 4:case'4': UxTCTL &=~ STC; USPI4ON;    break;  //四线模式

        default :       return(0);                          //参数错误

    }

    

    //------------------------设置UCLK模式-----------------------  

    switch(clkMode)

    {

        case 0:case'0': UxTCTL &=~ CKPH; UxTCTL &=~ CKPL;   break;  //模式0

        case 1:case'1': UxTCTL &=~ CKPH; UxTCTL |= CKPL;    break;  //模式1

        case 2:case'2': UxTCTL |= CKPH;  UxTCTL &=~ CKPL;   break;  //模式2

        case 3:case'3': UxTCTL |= CKPH;  UxTCTL |= CKPL;    break;  //模式3

        default :       return(0);                                  //参数错误

    }

    

    UxME |= USPIEx;             //模块使能

    

    UCTL0 &= ~SWRST;            // Initialize USART state machine

    

    UxIE |= URXIEx + UTXIEx;    // Enable USART0 RX interrupt 

    

    return(1);                  //设置成功

}

程序注释已经比较详细,这里不再细说;如果要改为从机模式,把时钟设置和波特率设置去掉应该就可以了。


发送函数和接收函数:


void SpiWriteDat(char c)

    while (TxFlag==0) SpiLpm();  // 等待上一字节发完,并休眠

    TxFlag=0;                     //

    UxTXBUF=c;

}

 char SpiReadDat()

    while (RxFlag==0) SpiLpm(); // 收到一字节?

    RxFlag=0;

    return(UxRXBUF);

}

发送和接收函数和异步通信里面的几乎一样,如果标志位为0,则等待改变为1,然后写入或读出;标志位在中断函数里被更改;中断函数如下:


#pragma vector=USARTxRX_VECTOR

__interrupt void UartRx()

{

    RxFlag=1;

    __low_power_mode_off_on_exit();

}

 #pragma vector=USARTxTX_VECTOR

__interrupt void UartTx ()

{

    TxFlag=1;

    __low_power_mode_off_on_exit();

}

中断里面仅仅置标志位后,就退出低功耗;退出后即写入或者读取数据。


读取或写入函数调用的SpiLpm函数:


void SpiLpm()

{

    if(UxTCTL&SSEL0) LPM3;  //若以ACLK 作时钟,进入LPM3休眠(仅打开ACLK)

    else             LPM0;  //若以SMCLK作时钟,进入LPM0休眠(不关闭SMCLK)

}

根据不同情况进入低功耗,如果单片机其他地方不允许进入低功耗,可以更改这个函数。


程序部分就这么多了。需要的函数在头文件里面声明,方便使用。


使用示例:

程序使用方式和之前的程序库相同,加入c文件,包含h文件,调用初始化函数后

[1] [2]
关键字:MSP430  程序库  SPI  同步串行通信 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic476706.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:MSP430程序库<六>通过SPI操作AD7708
下一篇:基于MSP430F413水果电池供电的低功耗时钟

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

MSP430程序库<十一>定时器TA的PWM输出
;          //TA PWM输出程序库头文件void main(){    // Stop watchdog timer to prevent time out reset    WDTCTL = WDTPW + WDTHOLD;    ClkInit();        TAPwmInit('A',1,'P','P');   //将定时器TA初始化成为PWM发生器   
发表于 2019-10-09
MSP430程序库<十一>定时器TA的PWM输出
MSP430程序库<十二>SVS(电源电压监控器)模块
电源电压监控对于单片机来说,也是经常要用的模块。当需要稳定的工业级产品时,经常要对电源电压监控,以保证单片机系统工作于正常环境或范围中。MSP430F16x提供了一个现成的电源电压监控器模块SVS,方便检测电源电压或者是外部电压,可以设置为电压过低时复位 或置标志位。本程序即完成SVS的设置使用的程序库(msp430f14x没有此模块)。硬件介绍:MSP430单片机含有的SVS模块可以很方便的监控电源电压或外部电压。电源电压监控器(SVS)是用于监控AVCC电源电压或外部电压。 SVS的可配置当电源电压或外部电压下降到低于用户选择的电压级别时设置一个标志,或产生POR复位。SVS模块有以下特点:可以监控AVCC电压;可选择产生
发表于 2019-10-09
MSP430程序库<十二>SVS(电源电压监控器)模块
MSP430程序库<十三>硬件乘法器使用
;/***************************************************************************** 名    称:main主程序* 功    能:硬件乘法器程序库使用演示* 入口参数:无* 出口参数:无****************************************************************************/void main( void ){    // Stop watchdog timer to prevent time out reset    WDTCTL = WDTPW + WDTHOLD; 
发表于 2019-10-09
MSP430程序库<十三>硬件乘法器使用
MSP430程序库<十四>DMA程序库
;     case 2: DMA2CTL |= DMAREQ;  break;      //2通道    }}这个和上个函数类似:仅仅设置一个控制位,函数很简单,不再解释啦。程序实现就这么多了,有关详细内容可以下载附件里的程序库,程序的注释很详细。使用示例:使用这个程序时,步骤和原来的相同:工程中加入DMA.c文件,然后源文件中包含DMA.h头文件即可。示例程序主要如下:#include <msp430x16x.h>#include "DMA.h"unsigned int
发表于 2019-10-09
MSP430程序库<十四>DMA程序库
MSP430程序库<十五>Flash控制器
一般,在单片机中的Flash存储器用于存放程序代码,属于只读型存储器。而在MSP430些列的单片机中,都可以通过内置的Flash控制器擦除或改写任何一段的内容。另外,msp430的单片机内部还专门留有一段Flash区域(information memory),用于存放掉电后需要永久保存的数据。利用430内部的Flash控制器,可以完成较大容量的数据记录、用户设置参数在掉电后的保存等功能。硬件介绍:要对Flash读写,首先要了解MSP430的存储器组织。430单片机的存储器组织结构采用冯诺依曼结构,RAM和ROM统一编址在同一寻址空间中,没有代码空间和数据空间之分。一般430的单片机都统一编址在0-64k地址范围中,只有少数高端
发表于 2019-10-09
MSP430程序库<十五>Flash控制器
MSP430程序库<十>ADC12模块
;   ADC12CTL0 &=~ ENC;                      //停止转换        i=0;    }}该程序实现的是多次A0-A2 32次转换,把结果存入results数组。单次时,仅仅采样一次(A0-A2)可用自己更改处理函数。程序部分就完成了,调用时注意要自己实现处理逻辑或存储逻辑。使用示例: 本程序使用方式还是加入C文件,包含H文件;不过和之前的程序不同的是要自己实现中断处理逻辑。使用示例参见程序库中
发表于 2019-10-09
MSP430程序库<十>ADC12模块
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved