SPI数据模式:
CPOL:SPI 时钟极性控制
0:SCLK 空闲时为低电平,SCLK 的前时钟沿为上升沿,后时钟沿为下降沿1:SCLK 空闲时为高电平,SCLK 的前时钟沿为下降沿,后时钟沿为上升沿CPHA:SPI 时钟相位控制
0:数据 SS 管脚为低电平驱动第一位数据并在 SCLK 的后时钟沿改变数据,前时钟沿采样数据(必须 SSIG=0)
1:数据在 SCLK 的前时钟沿驱动,后时钟沿采样
2.硬件连接
1.硬件链接
不过,我仔细在试验箱上找了,没有发现有 W25X40CL 芯片,可能是用其他芯片替换了吧?
CS:低电平有效DI/DO:数据输入输出端WP:低电平写保护HOLD:低电平时暂停CLK:时钟信号
这里芯片是用3.3V的:
接下来学习程序的编写:
先看好时序图:
我觉得没有单总线的18B20 那么清晰,有点乱:
1.SPI的IO口初始化2.SPI读取一个字节(MSB模式)3.SPI写入一个字节
我们写个模式0(CPOL=0和 CPHA=0)的程序:
先明确引脚:
//------------------------------引脚定义------------------------------
#define CS P22
#define MISOP24
#define WP P53
#define MOSIP23
#define SCLKP25
最关键是3个函数:
void SPI_Init() //SPI初始化
{
CS =1;//不选中该器件
MISO =1;//不要一开始就拉低引脚电平,避免从机发数据过来接收不到
WP =1;//不需要锁定
MOSI =1;//不需要锁定
SCLK =0;//SPI选模式0,初始化 CPOL=0
}
void SPI_WriteByte(u8 dat) //写一个字节
{
u8 i;
for(i=0;i<8;i++)//如果是MSB就先写高位
{
if( dat & 0x80)//判断最高位是1么?
MOSI = 1;
else
MOSI = 0; //和单总线不同,不用输出1码,直接就是高电平
SCLK =1; //产生一个下降沿
SCLK =0; //数据就传出去
dat<<=1; //再返回去循环第二位
}
}
u8SPI_RearByte() //读取一个字节
{
u8 i;
u8 dat;
for(i=0;i<8;i++)//如果是MSB就先写高位
{
dat<<=1; //最先接到的数据放在最高位
SCLK =0; //产生一个上升沿
SCLK =1; //数据就传出去
if( MISO)//判断MOSI是高位1么?这是从机往主机发送数据
dat |= 1;//一定是|=1
else
dat |= 0; //和单总线不同,不用输出1码,直接就是低电平
//再返回去循环第二位
}
return dat;
}
看看主函数:
void main() //程序开始运行的入口
{
int dat = 0; //初始数值
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
EUSB = 1;
Timer0_Init(); //定时器0初始化
EA = 1; //CPU开放中断,打开总中断。
while( DeviceState != DEVSTATE_CONFIGURED );
SPI_Init(); //SPI初始化
while(1) //死循环
{
u8ID;
delay_ms(2);
if( bUsbOutReady ) //单片机每接受到一次数据,就打印一次存储芯片的ID号回来串口
{
// USB_SendData(UsbOutBuffer,OutNumber);
usb_OUT_done();
CS = 0;
SPI_WriteByte(0xAB); //写入一个字节,0xAB命令,读取芯片ID
SPI_WriteByte(0x00); //写入一个字节,空命令,读取芯片ID
SPI_WriteByte(0x00); //写入一个字节,空命令,读取芯片ID
SPI_WriteByte(0x00); //写入一个字节,空命令,读取芯片ID
ID = SPI_RearByte(); //读取一个字节
CS = 1 ;
printf("本芯片的ID: %u\r\n", (u16)ID);//ID是无符号的8位变量 %u 对应u16,这是10进制打印
printf("本芯片的ID: %x\r\n", (u16)ID);//ID是无符号的8位变量 %u 对应u16,这是16进制打印
}
if( TIM_10MS_Flag==1 ) //如果10ms到了
{
TIM_10MS_Flag = 0; //清空标志位
}
//研究SPI时序图可知,SPI初始化结束后,往从机里发0xAB指令,接着发3个任意空指令,
//接着马上在D0上读取一个字节,这个字节就是芯片的ID
}
}
当然,看着冲哥写,跟着冲哥写,就容易
离开视频,真正自己对照时序图,能写出来并且调通,上机实验,能得到正确结果
那才是真的学会了!
好了,spi 就简单先到这里,其实还没完...................
前几天不知道什么原因,我的PC机(win10) 突然出来个毛病
鼠标右键要选择文件夹,就开始转圈,然后闪退,之后用了很多方法,都没有解决
只能重装系统,在网上找了个纯净的win10 ,装完系统后随便装了2个软件,故障又出现
后来没辙了,退会win7 ,好像问题就解决了,今天开始用一下win7 继续搞STC32G12K128的实验
接着看软件模拟SPI读取芯片ID的运行结果:
一个是16进制,一个是10进制