数码之家

 找回密码
 立即注册
搜索
查看: 5216|回复: 8

[C51] 说说STC12硬件SPI那点事,也请教代码原理【完整可用代码在7楼】

[复制链接]
发表于 2019-5-10 21:47:45 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 慕名而来 于 2019-5-11 15:37 编辑

先将自己理解的分享给大家:
STC12单片机的硬件SPI操作涉及三个寄存器,分别是控制寄存器SPCTL、状态寄存器SPSTAT、数据寄存器SPDAT,其中最复杂的是控制寄存器,设置控制寄存器的时候需要清楚被控SPI器件的时钟相位或者器件的SPI操作模式,对于W25Q64而言,他是在总线空闲状态时钟为低电平在上升沿采集数据,也就是前沿采样或第一个边沿采样后沿输出;说白了就是上跳脉冲触发,在已知这些后再来设置控制寄存器就简单了,直接SPCTL=0xD0(1101 0000)就好了,再说说这个数据的含义,7-0位依次为:SSIG=1忽略/SS由MSTR位决定主/从机;SPEN=1使能SPI;DORD=0高位先行;MSTR=1主机模式;CPOL=0、CPHA=0上跳脉冲前沿采集后沿输出;SPR1=0、SPR0=0总线时钟频率为单片机时钟4分频。
接下来说说状态寄存器,这个寄存器仅用到7、6两个位,第7位SPIF在输出传输一次完成时会自动置位为0,第6位是写冲突位,会在数据寄存器进行写操作是置位为0,这两个位需要软件写1清除标志。最后一个是数据寄存器,总线中无论是向器件写数据还是在总线上读取数据,都是通过这个寄存器来完成的,其他就没啥可说的了,具体例程可以参照数据手册就不贴了。
以上只是新手的学习心得,如有谬误请及时指正以免误导他人!

再把不懂的提出来请教大家:
以下是关于代码原理的问题,还请高手不吝赐教,先谢了!

1.对于清除标志位的操作,代码写作SPSTAT =0xc0;//1100 0000  这样就将寄存器中最高两位SPIF WCOL的0清除了;
而样例中写作SPSTAT = SPIF | WCOL;看着很高大上,但我真心没明白。
2.对于控制寄存器的设置,按照我上述文字描述的情形,只要SPCTL=0xD0(1101 0000)就好了,
而样例中写作SPCTL = SPEN | MSTR;这个我也不明白。


打赏

参与人数 2家元 +20 收起 理由
asusyt + 10 歡迎探討
家睦 + 10 歡迎探討

查看全部打赏

发表于 2019-5-10 23:57:37 | 显示全部楼层
就是个宏定义啊
回复 支持 反对

使用道具 举报

发表于 2019-5-11 08:11:48 | 显示全部楼层
只要SPCTL=0xD0(1101 0000)就好了,
而样例中写作SPCTL = SPEN | MSTR;这个我也不明白

代码写成 0xd0 你必须要查手册才知道啥意思

SPCTL = SPEN | MSTR    ; 这个定义,我没有查过手册,但是看文字的意思是使能SPI 和设置为主机模式

容易理解
回复 支持 反对

使用道具 举报

发表于 2019-5-11 08:18:21 | 显示全部楼层
这是宏定义……
回复 支持 反对

使用道具 举报

发表于 2019-5-11 08:32:35 来自手机浏览器 | 显示全部楼层
在样例中有宏定义,如:#define SPIF 0x10000000
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-11 15:15:56 | 显示全部楼层
多谢各位的指点,确实是有宏定义的,使用STC手册的例程我没仔细看上边一段的定义,因为以为那些sfr类的定义在引用头文件时就自动搞定了,结果仔细看了一下有好多的宏定义,都明白了,囧并感谢各位。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-11 15:34:10 | 显示全部楼层
已经调试、注释好的代码贴在这里,关于STC12单片机的硬件SPI代码真的不多,有用到的不用百度了,这个是驱动W25Q64用的,仅为总线驱动代码,具体的应用代码请自己添加,如果驱动其他器件请对应设置一下时钟相位。
新手使用只需建立两个文本文档并更改文件名称,而后复制粘贴保存,而后添加工程、调用文件啥的就多不啰嗦了。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
stc_spi.c
==============================================================================
#include<stc_spi.h>
void SPI_init()
{
SPDAT = 0; //清空数据寄存器
SPSTAT = 0xC0; //清除所有标志(共两个)0xC0
SPCTL = 0xD0; //0xD0;忽略SS-使能SPI-高位先行-主机模式-时钟空闲时为低、上升沿(第一个边沿)采样、后沿输出-CPU_CLK/4
}
//====SPI写一个数据字节函数==========================
//SPI状态寄存器SPSTAT的最高位为SPIF、每当一次串行传输完成时SPIF都会被置位为0、可以依次判断数据传输状态
void SPI_WriteByte(unsigned char temp)
{
SPDAT = temp;//待发送数据存入数据寄存器
while(!(SPSTAT & 0x80));//等待传输完成SPIF=0(无标志时SPIF=1、SPSTAT=0x80)
SPSTAT = 0xC0;//SPIF=1、WCOL=1清除标志
}
//====SPI读一个数据字节函数==========================
//硬件SPI总线发送与读回的数据皆暂存于SPI数据寄存器SPDAT中
unsigned char SPI_ReadByte()
{
SPDAT = 0x00;//清空数据寄存器
while(!(SPSTAT & 0x80));
SPSTAT = 0xC0;
return SPDAT;//返回读取的数据
}
=========================================================================

stc_spi.h
=========================
#ifndef __STC_SPI_H__
#define __STC_SPI_H__
#include <STC12C5A60S2.H>
void SPI_init();
void SPI_WriteByte(unsigned char temp);
unsigned char SPI_ReadByte();
#endif
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

打赏

参与人数 1家元 +20 收起 理由
家睦 + 20

查看全部打赏

回复 支持 1 反对 0

使用道具 举报

发表于 2020-3-11 18:49:53 | 显示全部楼层
别的论坛都找不到SPI的资料,看了数码之家两篇帖子搞通了,刷ILI9341可以了,
回复 支持 反对

使用道具 举报

发表于 2020-3-16 12:15:16 | 显示全部楼层
jhn609 发表于 2020-3-11 18:49
别的论坛都找不到SPI的资料,看了数码之家两篇帖子搞通了,刷ILI9341可以了, ...

把你从程序发来学习学习
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-3-29 06:39 , Processed in 0.140400 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表