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

  1. 硬件介绍:

    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线模式,控制多主从系统中多个从机,避免发生冲突。具体方式如下(图截自 用户指南):

    四线主机模式:STE为高电平,SIMO和UCLK操作正常;STE为低电平,SIMO和UCLK被置为输入方向,主机控制权让出。
    四线从机模式:STE为高电平,从机的发送和接收无效,且把SOMI置为输入方向;STE为低电平,发送接收正常,SOMI也为正常输出。

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

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

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

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

  2. 程序实现:

    程序和异步通信方式类似:首先是初始化函数,然后是读取数据、写入数据函数。此程序采用和我之前的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);            //分频系数必须大于2else{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;  //模式0case 1:case'1': UxTCTL &=~ CKPH; UxTCTL |= CKPL;    break;  //模式1case 2:case'2': UxTCTL |= CKPH;  UxTCTL &=~ CKPL;   break;  //模式2case 3:case'3': UxTCTL |= CKPH;  UxTCTL |= CKPL;    break;  //模式3default :       return(0);                                  //参数错误}UxME |= USPIEx;             //模块使能UCTL0 &= ~SWRST;            // Initialize USART state machineUxIE |= 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)
    }

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

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

  3. 使用示例:

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

    #include "msp430x16x.h"   //430寄存器头文件
    #include "Spi.h"         //串口通讯程序库头文件void main()
    {// Stop watchdog timer to prevent time out resetWDTCTL = WDTPW + WDTHOLD;ClkInit();// 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)SpiMasterInit(25000,8,3,0);_EINT(); while(1)                    //串口测试{SpiWriteDat(0X20);char a = SpiReadDat();}
    }

    这里只是一个简单的使用示例,详细的使用,将会在下一篇给出,下一篇:MSP430程序库<六>通过SPI操作AD7708;将会使用今天的程序库,完成SPI的通信部分。

  4. 注意事项:

    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 resetWDTCTL = WDTPW + WDTHOLD;ClkInit();// 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)SpiMasterInit(25000,8,3,0);_EINT(); while(1)                    //串口测试{SpiWriteData(0X20);     //只写入char a = SpiWriteData(0xff);    //只读取}
    }

    详细示例,参参考下一篇:MSP430程序库<六>通过SPI操作AD7708

SPI的通信部分完成,有什么不足,欢迎讨论。谢啦!

附件:程序库

作者:给我一杯酒
出处:http://Engin.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,转载保留此段文字并且注明出处;谢谢。

转载于:https://www.cnblogs.com/Engin/archive/2011/08/09/2133036.html

MSP430程序库五SPI同步串行通信相关推荐

  1. 把一个人的特点写具体作文_五年级下册第五单元同步作文《把一个人的特点写具体》范文4篇...

    五年级下册第五单元同步作文<把一个人的特点写具体>(范文) 憧憬学习 我的"洁癖"爸爸 我的爸爸中等个儿,粗粗的眉毛下有一双睿智的眼睛,高高的鼻梁上架着一副眼镜,嘴巴最 ...

  2. MSP430程序库九数码管显示

    数码管也是单片机系统最常用的输出设备之一(还有液晶.发光二极管等).七段(这里用的是8段,有小数点)数码管可以完成显示0-9数字和一部分的英文字符如:A.b.本文实现的程序完成显示数字和可显示的英文字 ...

  3. MSP430程序库二UART异步串口

    串行通信接口是处理器与其他设备进行数据通信最常用的方式之一.我的这个程序库是针对MSP430f14系列和MSP430f16系列的,我常用的单片机是这两款:msp430f149,msp430f169.这 ...

  4. asyncio 系列五、同步原语—Synchronization Primitives

    官网连接:https://docs.python.org/zh-cn/3.7/library/asyncio-sync.html 将 Synchronization Primitives 暂且翻译为同 ...

  5. MSP430 G2553 硬件SPI OLED 单片机 0.96英寸7针OLED SPI 6针OLED

    SSD1306通信方式靠硬件选择: 四线SPI(只针对SSD1306的一个名字)的OLED款式1 D0时钟 D1数据 RST复位 DC数据命令选择 四线SPI(只针对SSD1306的一个名字)的OLE ...

  6. MSP430程序库三12864液晶程序库

    液晶是单片机系统最常用的显示设备之一,这个程序库是在MSP430F169.MSP1430F149单片机上测试通过的,可以放心使用:液晶选用的是金鹏的:OCMJ4X8C型号的12864液晶:控制液晶用的 ...

  7. coursera 《现代操作系统》 -- 第五周 同步机制(1)

    临界区块(Critical section)指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源有无法同时被多个线程访问的特性.(不是字面意思的一个区域,是程序片段的集合) ...

  8. 8天玩转并行开发——第五天 同步机制(下)

    承接上一篇,我们继续说下.net4.0中的同步机制,是的,当出现了并行计算的时候,轻量级别的同步机制应运而生,在信号量这一块 出现了一系列的轻量级,今天继续介绍下面的3个信号量 CountdownEv ...

  9. MSP430 F5529 硬件SPI OLED 单片机 0.96英寸7针OLED SPI 6针OLED

    https://www.ti.com.cn/cn/lit/ds/symlink/msp430f5529.pdf?ts=1600611951477&ref_url=https%253A%252F ...

最新文章

  1. oracle维护数据的完整性
  2. 服务器虚拟化的培训,VMware服务器虚拟化及桌面虚拟化培训.pptx
  3. 【转载】一天之内上手.Net+WAP项目
  4. 生成用于ASP.NET Web API的C#客户端API
  5. 量化策略开发中的参数调优
  6. 开课吧课堂之throws如何去使用?
  7. Problem D: 平面划分
  8. 雨听|生成mac风格代码块
  9. 基于JDBC的宠物管理系统
  10. linux dns mx 记录,一起学DNS系列(十三)图文详说A、CNAME、MX和NS记录
  11. 程序员英文简历范例(通用,含初级、中级和高级)
  12. iOS关于应用出现未验证应用的解决方法
  13. 根据url 参数,页面显示不同背景图片
  14. nvidia agx xavier平台imx334 驱动调试记录
  15. JAVA学习 API_day10(缓冲流, 打印流, 对象流)
  16. 酷炫多彩的个性化词云可视化
  17. 总结Python设置Excel单元格样式的一切,比官方文档还详细
  18. gitbook 使用粘自csdn
  19. MATLAB之function函数
  20. 函数式编程:一等函数(First-class Function)

热门文章

  1. iOS开发线程同步技术-锁
  2. react学习(四)之设置 css样式 篇
  3. python -- 进程
  4. sqlserver字段选择参照
  5. nib、xib、storyboard(故事板)
  6. 【转】MySQL分库分表环境下全局ID生成方案
  7. 参与组织社区活动总结
  8. FLEX 运行 空白
  9. git push origin master和git push有什么区别?
  10. 华为链路汇聚命令(静态)