历史上的今天
今天是:2025年04月07日(星期一)
2021年04月07日 | 第五课 MC9S08DZ60之串行外围设备接口SPI
2021-04-07 来源:eefocus
本章节将浅析SPI通信原理,以及利用MC9S08DZ60单片机的串行外围设备接口SPI,实现SPI串行通信,MCU为主控设备。有兴趣的读者可以通过单片机的I/O口,模拟SPI通信过程,实现SPI通信。
1.理解SPI通信协议
读者可以到网盘https://pan.baidu.com/s/1yEoRjek9Oag5iEpp40nYYQ下载 这篇文章很简洁的介绍了SPI通信协议和工作原理,初识SPI通信的读者请认真阅读。 作者在此简短说明SPI通信原理。 如下图,主设备(Master)要发送0x66给从设备(Slave),同时从设备(Slave)也会把0xC5发送给主设备(Master); 每个CLKx周期,主从设备做了一个bit位的数据交换,数据交换为byte单位,需要循坏8CLK周期。 从而分析出SPI具备的几个特点: 主从模式(Master->Slave):主设备是主控制设备,控制从设备的选取和时钟驱动。 同步方式(synchronize):根据时钟信号同步数据的收发。 交换数据方式(exchange):在每个时钟周期CLK内,主从SPI设备都会发送并接受一个bit大小的数据。 2.SPI工作方式 如下图: 先往 Master 的 Tx-Data 寄存器写入将要发送出去的数据(有时为了读取从设备可以发送dummy数据), 这些数据会被 Master-SSPSR 移位寄存器根据 Bus-Width 自动移入 Master-SSPBUF 里, 然后这些数据又会被 Master-SSPSR 根据 Channel-Width 从 Master-SSPBUF 中移出, 通过 Master-SDO 管脚传给 Slave-SDI 管脚, Slave-SSPSR 则把从 Slave-SDI 接收到的数据移入 Slave-SSPBUF 里. 与此同时, Slave-SSPBUF 里面的数据根据每次接收数据的大小(Channel-Width), 通过 Slave-SDO 发往 Master-SDI, Master-SSPSR 再把从 Master-SDI 接收的数据移入 Master-SSPBUF.在单次数据传输完成之后, 用户程序可以通过从 Master 设备的 Rx-Data 寄存器读取 Master 设备数据交换得到的数据. Bus-Width :即上图寄存器Tx_Data到SSPBUF总线位宽。 Channel-Width:即上图SDO->SDI的数据带宽,也可以理解为主设备到从设备或从设备到主设备每次发送的数据宽度,一般是一个字节。 3.阅读芯片资料理解MC9S08DZ60的SPI 大家可以到百度网盘下载该芯片的中英文的资料https://pan.baidu.com/s/1dgVbkE https://pan.baidu.com/s/1o9qFU5c 进入第十三章 串行外围接口SPI(Serial peripheral Interface) a.从Figure 13-1. MC9S08DZ60 Block Diagram节中,加黑部分总览SPI模块及其接口。该芯片中提供一路SPI接口,接口还将占用端口E的4个I/O口。 b. 13.1.1 Features节中特性 目前普遍拥有SPI通信模块芯片的基本特性,这里说明下MSB和LSB。 最高有效位(MSB),指二进制中代表最高值的比特位,这一位对数值的影响最大。例如,在二进制的1001(十进制的9) 中,最左边的“1”对数值影响最大:1到9的变化幅度。而最右边的1仅会让数值产生8到9的变化,故该位称也为最低有效位LSB(Least Significant Bit)。 如果设置为MSB发送模式,那么一个byte数据在从SDO->SDI过程,是先发送最左边的bit位,如果是LSB,那么相反。这里还有个概念,叫着大小端。在嵌入式网络开发中,经常提到。有兴趣的读者可以通过互联网搜索等方式,了解这个大小端的概念。 c. 13.1.2.2 SPI Module Block Diagram 这里面讲了很多(芯片资料建议看英文的,中文部分有误),最简单的就理解这句话就行“In the external SPI system, simply connect all SPSCK pins to each other, all MISO pins together MOSI pins together. Peripheral devices often use slightly different names for these pins.”在硬件层面,主从设备把相同名字的接口连接即可。至于SPI模块内部的route(接收或发送的线路选择),能理解就理解。 d. 13.1.3 SPI Baud Rate Generation 这小节介绍了Baud波特率的时钟源,看下图,时钟源来源于BUS CLOCK总线时钟,在本系列博文中《第二课 MC9S08DZ60之多功能时钟发生器S08MCGV1》有介绍,且该单片机的SPI时钟源只能来源于总线时钟。BUS CLOCK时钟来源于MCGOUT的时钟,且BUS CLOCK为MCGOUT时钟的一半。这里将利用《第二课 MC9S08DZ60之多功能时钟发生器S08MCGV1》中代码设置好的时钟作为SPI的驱动时钟。其中MCGOUT为40mHz,那么BUS CLOCK就是20mHz。 总线时钟BUS CLOCK经过预分频PRESCALER和时钟速率除数CLOCK RATE DIVIDER,最终才得到SPI的驱动时钟。波特率一般用位每秒(bit/s)作为单位,通俗的理解就是:一秒钟能发送多少位。举个例子:假如分频后SPI的驱动时钟为T=1ms(1kHz),那么波特率为baud=1000bps————一秒钟可以传输1000bit的数据。 e. 13.2.2 MOSI — Master Data Out, Slave Data In和13.2.3 MISO — Master Data In, Slave Data Out两小节,除了介绍了标准4线模式的SPI通信,还介绍了single-line bidirectional Mode(一根数据线,主master到从slave间的双向通信模式),在这种模式下,只需要时钟线SCK、片选线CS/SS和一根数据线SD,即可完成SPI主从的硬件连接。这将节省一路I/O管脚,节省的管脚分别为主设备的MISO和从设备的MOSI,而原来主设备的MOSI更名为MOMI,原来从设备的MISO更名为SISO.(芯片资料建议看英文,中文有错误)。 f. 13.2.4 SS — Slave Select 这小节介绍了SS片选管脚,读者要了解,当从设备只有一个,不需要片选的时候,主设备的SS管脚是可以空出来做为通用I/O口的(在硬件上面还需要配合)。 g. 13.5 Functional Description 这小节讲了MC9S08DZ60 MCU提供的一些SPI功能模块的特性,其中 的故障模式(SS管脚配置为故障检测口)“The mode fault detection feature can be used in a system where more than one SPI device might become a master at the same time. ”用于在多个SPI设备间的主从权衡。在一些应用场合,这些SPI设备既可以为主模块去寻址其它设备,又可以为从模块而被寻址。当为主SPI模块的设备被寻址,那么模式错误会被置起。置起的故障可以通过设置一个终端服务进行处理。 h. 13.6 Initialization/Application Information 这小节提供了 SPI初始化过程和一个伪例子。这里把资料中的Initial sequence 初始化过程的文字拷贝过来: 1. Update control register 1 (SPIC1) to enable the SPI and to control interrupt enables. This register also sets the SPI as master or slave, determines clock phase and polarity, and configures the main SPI options. SPIC1寄存器控制SPI模块的使能和中断的使能,同时SPI从从模式的选择、时钟相位CPHA、时钟记性CPOL和主要的SPI选项也有SPIC1寄存器来设置 2. Update control register 2 (SPIC2) to enable additional SPI functions such as the master mode-fault function and bidirectional mode output. Other optional SPI functions are configured here as well. SPI的额外功能有SPIC2寄存器来设置,例如模式错误功能和单线双向通信功能。其他附加的SPI功能也在此寄存器设置。 3. Update the baud rate register (SPIBR) to set the prescaler and bit rate divisor for an SPI master. 预分配和速率除数计算的波特率在寄存器SPIBR中设置。 3.代码实现 本代码提供初始化和设置SPI功能的函数,并提供一个轮询方式的SPI访问实例。总线BUS CLK为20mHz。时钟设置采用《第二课 MC9S08DZ60之多功能时钟发生器S08MCGV1》设置好的。 头文件.H #ifndef _DATA_TYPE_H_H #define _DATA_TYPE_H_H typedef char INT8; typedef unsigned char UINT8; typedef unsigned short USHORT16; typedef unsigned int UNIT16; typedef unsigned long ULONG32; typedef short SHORT16; typedef long LONG32; typedef unsigned char BOOL; #endif #ifndef _SPI_H_H_ #define _SPI_H_H_ //SPI Control Register1-------------------------------------------------------- /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 |0 | R |-----------------------------------------------| |SPIE |SPE |SPTIE |MSTR |CPOL |CPHA |SSOE |LSBFE| W |-----------------------------------------------| Reset| 0 | 0 | 0 | 0 | 0 | 1 | 0 |0 | */ #define SPIC1_RESET 0x04 //reset value //Table_1 #define RESET_SPIC1 0xAA #define SPI_INTERRUPT_ENABLE 7 //When SPRF or MODF is 1,request HW INTR. #define SPI_INTERRUPT_DISABLE (~7) //use polling #define SPI_ACTIVE 6 //SPI system enabled #define SPI_INACTIVE (~6) //SPI system inactive #define SPI_TX_INTERRUPT_ENABLE 5 //When SPTER is 1,hardware interrupt reqested. #define SPI_TX_INTERRUPT_DISABLE (~5)//use polling #define SPI_AS_MASTER 4 //SPI mode configured as a MASTER. #define SPI_AS_SLAVE (~4) //SPI mode configured as a SLAVE. #define SPI_CLK_IDLES_HIGH 3 //Active-low SPI clock #define SPI_CLK_IDLES_LOW (~3) //Active-high SPI clock #define SPI_DATA_CHANGE_0N_FALLING_EDGE 2 //First edge on SPSCLK at the start. #define SPI_DATA_CHANGE_ON_RISING_EDGE (~2)//First edge on SPSCK occurs at the middle. #define SPI_SSOE_SET_ONE 1 //use to set SS pin Function #define SPI_SSOE_SET_ONE_REVERSE ~1 //use to set SS pin Function #define SPI_LSB_DATA_FLOW 0 //LSB Transfer mode #define SPI_MSB_DATA_FLOW ~0 //MSB Transfer mode /* Update control register 1 (SPIC1) to enable the SPI and to control interrupt enables. This register also sets the SPI as master or slave, determines clock phase and polarity, and configures the main SPI options. Parameter FuncValue为Table_1中的值。 */ void SetSPICtrlRegister1(UINT8 FuncValue); //SPI Control Register2-------------------------------------------------------- /* 7 6 5 4 3 2 1 0 -------------------------------------------- R |0 |0 |0 | | | 0 | | | |--|--|--|MODFEN |BIDIROE|----|SPISWAI|SPC0| | N|N |N | | | N | | | -------------------------------------------- Reset| 0| 0| 0| 0 | 0 | 0 | 0 | 0 | */ #define SPIC2_RESET 0x00 //reset value //Table_2 #define RESET_SPIC2 0xAA //Reset command #define MODE_FAULT_ENABLE 4//Mode fault function enabled,master SS pin acts as //the mode fault input or the slave select output. #define MODE_FAULT_DISABLE (~4)//Mode fault function disabled,master SS pin reverts //to general-purpose I/O not controlled by SPI. #define DATA_IO_AS_OUTPUT 3 //SPI I/O pin enabled as an output #define DATA_IO_AS_INPUT ~3 //Output driver disabled so SPI data I/Opin act as input. #define SPI_CLK_STOP_IN_WAIT_MODE 1//SPI clock stop when the MCU enters wait mode. #define SPI_CLK_OPER_IN_WAIT_MODE (~1)//SPI clocks continue to operate in wait mode #define SPI_SINGLE_WIRE_MODE 0 //SPI configured for single-wire bidirectional operation #define SPI_TWO_WIRE_MODE (~0)//SPI uses separete pins for data input and data output. /* Update control register 2 (SPIC2) to enable additional SPI functions such as the master mode-fault function and bidirectional mode output. Other optional SPI functions are con?gured here as well. FuncValue 使用Table_2 */ void SetSPICtrlRegister2(UINT8 FuncValue); //SPI Baud Rate Register ------------------------------------------------------ /* |7 6 5 4 3 2 1 0 | R |--|-----|------|-----|---|-----|----|------| |0 |SPPR2| SPPR1|SPPR0| 0 |SPR2 |SPR1| SPR0 | |--|-----|------|-----|---|-----|----|------| Reset| 0| 0 | 0 | 0 |0 |0 |0 |0 | = Unimplemented or Reserved */ //baudRate 参数单位为kbps //BusClk 参数单位为kHz 该频率为MCGOUT 频率的一半 //确保Bus/baudRate等于如下表格中的值: /* 2 4 8 16 32 64 128 256 |-------------------------------------------| 1| 2 |4 |8 |16 |32 |64 |128 |256 | |------|---|---|-----|-----|-----|----------| 2| 4 |8 |16 |32 |64 |128 |256 |512 | 



史海拾趣
|
国内站点: 华恒公司的主页,里面有很多的相关资料,有待大家去发现 http://www.hhcn.com/chinese/embedlinux-res.html SkyEye嵌入式硬件仿真项目 www.skyeye.org http://gro.clinux.org/projects/skyeye/ 公社的SkyEye项目专栏 http://www. ...… 查看全部问答> |
|
国标DMB_TH 地面高清数字信号加大覆盖 地面高清机 蓝光高清机 海美HD100重拳出击 依托于北京奥运会的隆重开幕,2008年5月1日,备受关注的央视高清综合频道正式开播。 CCTV-高清频道的开播,对于国家地面数字传输信号DMB-TH的发展具有里程碑的意义。 去年奥运期间,国家确定6+2城市陆续开播地面数字高清信号,让众多用户率 ...… 查看全部问答> |
|
不知道哪位验证过没有,这个电路中的431不会冒烟吗431的Datasheet中明确的说阴极和阳极间的最大压差为37V,这个电路中的压差有70多V, 居然这个电路在很多书上和网上看到,不知道是谁开发的??? … 查看全部问答> |
|
一:成本节约 现象一:这些拉高/拉低的电阻用多大的阻值关系不大,就选个整数5K吧 点评:市场上不存在5K的阻值,最接近的是4.99K(精度1%),其次是5.1K(精度5%),其成本分别比精度为20%的4.7K高4倍和2倍。20%精度的电阻阻值只有1、1.5、2.2、3 ...… 查看全部问答> |
|
下面的文章是从上次发的连接中整理出来的,写的挺好。拿出来和初学者朋友们一起学习,希望大家可以早日学好嵌入式技术。 嵌入式资深工程师白话说“嵌入式” 本文转引自 飞凌嵌入式 技术文章专区 www.witech.com.cn 从事嵌入式开发有些年头 ...… 查看全部问答> |
|
工具Windows CE Remote Heap Walker的问题. 在VS2005/WinCe6.0中, 工具Windows CE Remote Heap Walker [Process_List] 上, 自已写的程序,有的有二条对应记录, 如下: XXX.exe XXX.exe HF32_DEFAULT 有的只有一条对应记录, 如下: XXX.exe & ...… 查看全部问答> |
|
串口通讯中的7位数据位,和8位数据位,在实际数据通信中除了MS串口通信控件的数据位参数不同以外还有其他要求吗?比如在内容读取时需要额 串口通讯中的7位数据位,和8位数据位,在实际数据通信中除了MS串口通信控件的数据位参数不同以外还有其他要求吗?比如在内容读取时需要额外的解码过程吗?… 查看全部问答> |
|
请问,用2407如何实现每进一次中断进行连续多次A/D采样? 请问,用2407如何实现每进一次中断进行连续多次A/D采样,要求这多次采样的结果保证都取走。 是否可以通过判断相关寄存器的采样… 查看全部问答> |




