历史上的今天
返回首页

历史上的今天

今天是:2024年10月10日(星期四)

正在发生

2020年10月10日 | 【STM8】SPI通讯

2020-10-10 来源:eefocus

这篇内容有点长,如果有人想透过我的博客学习STM8的SPI,那是我的荣幸


首先我要先说大纲,这样大家心里比较有底,可以把精力都用在SPI理解上


【SPI初步介绍】:介绍SPI如何接线、名称解释、通讯注意事项

【SPI引脚 - 初始化(上)】:相对于STM8,SPI的引脚位置说明,还有引脚的设置,另外还有初始化的部分代码

【SPI寄存器 - 初始化(下)】:使用寄存器做一些设定,例如波特率、SPI开启或关闭、SPI中断、传输方式。。。太多了,要看寄存器手册,我有整理图片出来,另外还包括完整的初始化代码

【SPI通讯】:SPI发送数据、SPI轮询方式接收数据、SPI中断方式接收数据

【SPI初步介绍】

下图是SPI的通讯方式

M:Master(主)

S:Slave(从)

I:Input(输入)

O:Output(输出)

MISO:主设备(M)接收(I)数据,从设备(S)输出(O)数据

MOSI:主设备(M)输出(O)数据,从设备(S)接收(I)数据

SCK:时钟讯号

GPIO:普通I/O口

NSS:或叫SS,由外部的高低电平决定自己是主机还是从机,在STM8里,可以由软件决定,从而省下一个引脚去做别的事情,其他的芯片,就要去看datasheet才知道了

CS:片选(不一定会有),从机决定接收数据的依据,应用在SPI一主多从,就像广播一样,『一年二班小朋友起立!』,但一年一班的小朋友也听到了,不过你不要起立啊,当然,一主一从也有可能用到的

 

上面解释了各引脚功能,下面解释SPI的通讯方式:

MOSI:主机发送线路。额外说明,主机想收到从机数据,主机要提供SCK,但是产生SCK的唯一条件,就是主机要发数据出去,哪怕是无意义的数据(伪字节),不管主机想发还是收,都不能省略这条线

MISO:如果不打算接收从机数据,就不要接了,如果想收,作为配套的,SCK这条线就必然要接上了

SCK:可接可不接,不接的情况下,是从机已经规定好接收格式,主机必须按照这个格式发送

NSS:可接可不接,上面解释过了

CS:可接可不接,上面也解释过了

 

最后一点,主机和从机的GND要连上,原理我不知道,这经验是从串口(UART)学来的,任何通讯方式都要共地

 

【SPI引脚 - 初始化(上)】

因为我是用STM8S开发板来研究的,所以内容就局限在这里,链接是我的另一篇博客,介绍开发板和一些工具https://www.cnblogs.com/PureHeart/p/10824556.html

下面是引脚图

 

这就是SPI相关的引脚,文章一开始也说了,某些情况下,可以省略几个引脚

然后要说设置的部分了

MISO要设置成『弱上拉输入模式』

MOSI、SCK要设置成『推挽输出模式』

为什么设置成这样,原理我不懂,但是能实现就好了不是吗?

在现今社会里,没有成功就代表什么都不是,可以纠结原理,但不是必要?

扯远了,回来说正题,这两种模式,需要看寄存器手册,我知道有人是用『库』来开发

但我自学的时候就学寄存器了

下面这张图,是GPIO的设定

MISO对应的引脚是PC7,设定为『弱上拉输入模式』,所以DDR=0,CR1=1,CR2=0

MOSI对应的引脚是PC6,设定为『推挽输出模式』,所以DDR=1,CR1=1,CR2=0

SCK对应的引脚是PC5,设定为『推挽输出模式』,所以DDR=1,CR1=1,CR2=0

NSS我不想外部控制,想用软件的方式选择是主机还是从机,在后续文章关于SPI寄存器会有说明

有了这份数据,可以写代码了,不过先上一张Px_DDR寄存器的图,关于GPIO的寄存器,我觉得看上面的表格应该就够了,上图只是说明对应位置

PC_DDR = 0x60; // 0110 0000

PC_CR1 = 0xe0; // 1110 0000

PC_CR2 = 0x60; // 0110 0000

 

/* ==================== 分割线 ====================== 上方是寄存器控制,相对来说比较简洁的写法 */

/* ==================== 分割线 ====================== 下方是比较针对的写法,直接控制寄存器内的某一位,两种写法选一个即可 */

 

PC_DDR_DDR5 = 1;    // 配置PC5(SCK)端口为输出模式

PC_CR1_C15 = 1;     // 配置PC5(SCK)端口为推挽输出模式

PC_CR2_C25 = 1;     // 配置PC5(SCK)端口为高速率输出

     

PC_DDR_DDR6 = 1;    // 配置PC6(MOSI)端口为输出模式

PC_CR1_C16 = 1;     // 配置PC6(MOSI)端口为推挽输出模式

PC_CR2_C26 = 1;     // 配置PC6(MOSI)端口为高速率输出

     

PC_DDR_DDR7 = 0;    // 配置PC7(MISO)端口为输入模式

PC_CR1_C17 = 1;     // 配置PC7(MISO)端口为弱上拉输入模式

PC_CR2_C27 = 0;     // 禁止PC7(MISO)端口外部中断


关于『寄存器』和『寄存器的某一位』,直接用一个例子来解释比较快

【所有一年级的学生去操场】【一年一班的同学去操场】

『寄存器』就相当于一年级

『寄存器的某一位』就相当于一年级的某一班

上面也说了,分割线的上方和下方,选择一个来用即可

 

上面代码的变量,全部都定义在『iostm8s103F3.h』里面了,当然,这是官方的头文件里面的内容,不是我自己命名这些变量的

貌似官方没有SPI范例,但是有Timer、UART之类的范例,随便拿一个来添加SPI代码即可

这是官方全部范例的链接,提取码是gszh,需要请自取https://pan.baidu.com/s/1La0LdFQxKl2_AyZXkBkv3w

 

【SPI寄存器 - 初始化(下)】

 

虽然图片有点多,但是代码没几行的

下面我直接贴上我测试时的代码,具体情况可能大家都不同,寄存器的几个位修改一下就好了,我直接配合『初始化-上』的代码一起贴出来

 其实整个初始化的思路如下

1.打开SPI时钟

2.引脚配置

3.开启SPI中断(如果不需要则不用开)

4.设置SPI_CR1(SPI控制寄存器1)

5.设置SPI_CR2(SPI控制寄存器2)

6.开启SPI


void Init_SPI(void)

{

    CLK_PCKENR1 |= 0x02; //打开SPI时钟

    /*PC6、PC5设置为输出,最大10MHz*/

    //PC_DDR = 0x60; // 0110 0000

    //PC_CR1 = 0xe0; // 1110 0000

    //PC_CR2 = 0x60; // 0110 0000

     

    PC_DDR_DDR5 = 1;    // 配置PC5(SCK)端口为输出模式

    PC_CR1_C15 = 1;     // 配置PC5(SCK)端口为推挽输出模式

    PC_CR2_C25 = 1;     // 配置PC5(SCK)端口为高速率输出

     

    PC_DDR_DDR6 = 1;    // 配置PC6(MOSI)端口为输出模式

    PC_CR1_C16 = 1;     // 配置PC6(MOSI)端口为推挽输出模式

    PC_CR2_C26 = 1;     // 配置PC6(MOSI)端口为高速率输出

     

    PC_DDR_DDR7 = 0;    // 配置PC7(MISO)端口为输入模式

    PC_CR1_C17 = 1;     // 配置PC7(MISO)端口为弱上拉输入模式

    PC_CR2_C27 = 0;     // 禁止PC7(MISO)端口外部中断

     

    SPI_ICR_RXIE = 1; // 开启SPI中断接收(下方备注)

     

    // [7]先发MSB

    // [6]禁止SPI

    // [5][4][3]f_Master / 2

    // [2]主设备

    // [1]空闲时SCK保持低电平

    // [0]数据采样从第一个时钟沿开始

    SPI_CR1 = 0x04; /*MSB、1MHz、主设备、CPOL空闲为低、CPHA第一个时钟开始*/

     

    // [7]双线单向模式

    // [6]输入使能(只接收模式)

    // [5]CRC计算禁止

    // [4]下个发送数据来自Tx缓冲

    // [3]保留

    // [2]全双工(同时收发)

    // [1]使能软件从设备管理(不需要判断硬件CS位,节省一个引脚)

    // [0]主模式

    SPI_CR2 = 0x03; /*双线单向视距传输、CRC计算禁止、软件NSS、主模式*/

     

    SPI_CR1_SPE = 1; // 打开SPI

}

备注:关于中断的部分,如果想要使用,还必须加上一行代码『asm("rim");』,通常加在main函数里面的while(1)之前

这个代码就像电源的总闸一样,你房间的电闸打开了,但总闸没开,结果还是没有电


当然有一个相对应的,就是关闭总闸『asm("sim");』


【SPI通讯】


终于到最后的环节了,关于发送和接收,接收又分两种,轮询和中断


直接上代码吧,也没几行



/* SPI发送 */

void SPI_sendchar(unsigned char c)

{

    while(!(SPI_SR & 0x02));    // 等待发送缓冲区『为』空

    SPI_DR = c;                  // 将发送的数据写到数据寄存器

    //while(!(SPI_SR & 0x01));    // 轮询的方式,等待接收缓冲区『非』空

    //UART1_sendchar(SPI_DR); // 备注

}

 

/* SPI中断 */

#pragma vector=SPI_RXNE_vector

__interrupt void SPI_RXNE_IRQHandler(void)

{

    //RxBuf[cnt++]=SPI_DR;

    while(!(SPI_SR & 0x01)); // 轮询

    UART1_sendchar(SPI_DR); // 备注

}


备注:我用很迂回的方式来显示结果,逻辑分析仪抓SPI还没研究成功,所以我借用了UART(串口)


轮询或中断接收到数据,透过串口把数据发送给『USB转TTL小板』,在电脑上用串口调试助手显示出来


终于写完了,谢谢你的观看,希望对你有帮助

推荐阅读

史海拾趣

Fairchild (ON Semiconductor)公司的发展小趣事

2016年,Fairchild Semiconductor被ON Semiconductor收购。这一收购标志着Fairchild Semiconductor的发展进入了一个新的阶段。ON Semiconductor是一家全球领先的半导体公司,拥有广泛的产品线和强大的技术实力。通过整合Fairchild Semiconductor的技术和资源,ON Semiconductor进一步巩固了其在半导体行业中的领导地位,并继续为全球客户提供优质的半导体产品和服务。

ANADIGICS公司的发展小趣事

随着技术的不断进步和市场的不断扩大,Fairchild Semiconductor开始将目光投向全球市场。公司积极开拓海外市场,与全球各地的企业建立合作关系,共同推动半导体技术的发展。通过不断努力,Fairchild逐渐在全球半导体市场中占据了重要地位。

鸿展光电(GPO)公司的发展小趣事

随着技术的不断进步和市场的不断扩大,Fairchild Semiconductor开始将目光投向全球市场。公司积极开拓海外市场,与全球各地的企业建立合作关系,共同推动半导体技术的发展。通过不断努力,Fairchild逐渐在全球半导体市场中占据了重要地位。

BRIGHT公司的发展小趣事

BRIGHT公司不仅在电子产品领域取得了成功,还积极拓展酒店业务。他们成立了伯瑞特酒店集团,并在全国范围内开设了多家酒店。这些酒店以高品质的服务和独特的文化特色赢得了广大消费者的喜爱。其中,宁波伯瑞特酒店荣获了全国钻级酒店评定中的五钻酒家称号,千岛湖伯瑞特度假酒店也获得了金鼎特色文化主题饭店的荣誉。这些荣誉的获得不仅彰显了BRIGHT公司在酒店业务方面的实力,也为其未来的发展奠定了坚实的基础。

EMC Technology RF Labs公司的发展小趣事

随着对射频技术的深入研究,RF Labs在多个领域取得了技术突破。他们成功开发了一系列高性能的射频电阻、衰减器、定向耦合器等关键元件,这些产品不仅具有优异的性能,而且能够满足各种复杂的应用场景需求。同时,RF Labs还不断推出创新产品,如智能探测器温度测量端子等,这些产品为客户提供了更加便捷和高效的解决方案。

Hosiden Corporation公司的发展小趣事

随着全球市场的不断扩展,Hosiden积极实施全球化战略,以满足全球客户对高质量电子产品的需求。公司不仅在日本本土拥有强大的生产基地和销售网络,还通过设立海外分支机构、与国际知名企业建立战略合作关系等方式,不断拓宽其全球市场版图。例如,Hosiden在中国市场通过投资豪熙电电子(上海)有限公司等方式,加强了其在中国及亚太地区的业务布局。

问答坊 | AI 解惑

印制电路工艺制程

印制电路工艺制程…

查看全部问答>

视频监控系统智能化如何在金融行业的应用

银行营业网点众多,遍布城乡的各个角落。而各个网点、自助银行ATM机的使用环境各不相同,安全防范系统必须克服这些环境因素的影响。这使得金融系统对产品的需求,相对于其它行业要高得多。例如,银行营业网点内部的场景监控,要选用高信噪比的摄像 ...…

查看全部问答>

批处理问题

我想请问下,我想要实现批处理开机就运行某指令,要怎么在内核里添加啊。。哪位帮帮忙!谢了…

查看全部问答>

wince内核调用API函数出问题

在kernel里面调用API函数都会出现连接错误,请问高手如何解决? hal.lib(cfw.obj) : error LNK2019: unresolved external symbol MapViewOfFile referenced in function OEMInit hal.lib(cfw.obj) : error LNK2019: unresolved external symbol Cr ...…

查看全部问答>

求PDA无线点餐设计 现金酬谢!!!

客户要求在我们现有的餐饮管理系统上,增加PDA无线点餐功能,请高手帮助,现金酬谢!!! 要求:读取指定的表的内容,点单成功写到指定数据表中 数据库:SQLSERVER 联系方式: yuan_zhzh@163.com QQ:2346855117…

查看全部问答>

华为公司北京研究所目前正在进行社会招聘

华为公司北京研究所目前正在进行社会招聘,主要从事数通产品的开发工作,要求如下: 1、必须是06年07月之前毕业的,有工作经验,如果是考研没考上也可以; 2、开发工具是C语言; 3、最好有一定的操作系统和TCP/IP基础。 有意向的请把简历发到我 ...…

查看全部问答>

全新 C2000™ F2833x 教学 ROM 现已推出

全新 C2000™ F2833x 教学 ROM 现已推出 全新 C2000 F2833x 教学 ROM 是一款综合指南,旨在向新用户介绍关于 C2000 与 F2833x 器件的全部知识。该教学 ROM 的内容结构类似于本科生教材,针对自学和辅导教学进行了精心设计。     ...…

查看全部问答>

STM32ISP-IAP及延长STM32寿命

东西很多,不直接贴,博客里去下 http://blog.eeworld.com.cn/user1/5817/archives/2009/63307.html…

查看全部问答>

关于can通信部分

用两块开发板下的can程序,之间能通信,现在我拿了另外自己设计的一块板,这块板只要收到can发送的信号就会有反应,那么原来的开发板只是发送CAN信号就可以,那么我除了修改发送的ID号以外,还应该修改什么吗,有什么需要注意的吗?谢谢啦…

查看全部问答>