1766|0

3836

帖子

19

TA的资源

纯净的硅(中级)

楼主
 

MSP430程序库<五>SPI同步串行通信 [复制链接]

  • 程序实现:
    程序和异步通信方式类似:首先是初始化函数,然后是读取数据、写入数据函数。此程序采用和我之前的UART程序库类似的结构,写入数据后进入低功耗等待中断,判断标志位进行写入数据和读取数据。
    这里函数只实现430的主机模式,如需从机模式可以仿照我的程序,进行简化实现。
    由于,我即将使用的SPI设备(AD7708)不是字符型设备,这里不再实现写入字符串函数,也不再移植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文件,调用初始化函数后即可掉用程序库中的函数。
    #include "msp430x16x.h"   //430寄存器头文件#include "Spi.h"         //串口通讯程序库头文件void main(){    // Stop watchdog timer to prevent time out reset    WDTCTL = WDTPW + WDTHOLD;        ClkInit();    // 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)    SpiMasterInit(25000,8,3,0);    _EINT();             while(1)                    //串口测试    {        SpiWriteDat(0X20);        char a = SpiReadDat();    }}
  • 注意事项:
    SPI是全双工通信,每次写入(发送)8位/7位数据的同时,430的SPI主模块都会在发送后半个时钟周期读取采样的0/1信号,存入接收缓冲寄存器,所以,每次的写入,均有数据读取,但不一定是从设备发送回来的,这个地方在使用430主机模式的时候必须注意,很容易出错(我也是在调试AD7708的时候才注意到这个地方的);SPI的函数已经添加SpiWriteData函数,这个函数会在发送的同时返回发送完成半个时钟周期后的接收到的数据,方便使用;不建议使用前面的发送和读取函数,很容易出错;建议使用刚添加的这个函数,程序库已经更新,可以重新下载。函数SpiWriteData:
    char SpiWriteData(char c){    SpiWriteDat(c);    return SpiReadDat();}
    发送后读取即可,程序比较简单。
    新的示例程序:
    void main(){    // Stop watchdog timer to prevent time out reset    WDTCTL = WDTPW + WDTHOLD;        ClkInit();    // 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)    SpiMasterInit(25000,8,3,0);    _EINT();             while(1)                    //串口测试    {        SpiWriteData(0X20);     //只写入        char a = SpiWriteData(0xff);    //只读取    }}

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表