找回密码
 立即注册
楼主: wuzhengmin

第一次:环境的创立 | 送实验箱

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:45 | 显示全部楼层
SPI数据模式:



CPOL:SPI 时钟极性控制
0:SCLK 空闲时为低电平,SCLK 的前时钟沿为上升沿,后时钟沿为下降沿1:SCLK 空闲时为高电平,SCLK 的前时钟沿为下降沿,后时钟沿为上升沿CPHA:SPI 时钟相位控制
0:数据 SS 管脚为低电平驱动第一位数据并在 SCLK 的后时钟沿改变数据,前时钟沿采样数据(必须 SSIG=0)
1:数据在 SCLK 的前时钟沿驱动,后时钟沿采样



截图202510131945328397.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:48 | 显示全部楼层
2.硬件连接
1.硬件链接

不过,我仔细在试验箱上找了,没有发现有 W25X40CL 芯片,可能是用其他芯片替换了吧?



截图202510131946546539.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:49 | 显示全部楼层
CS:低电平有效
DI/DO:数据输入输出端
WP:低电平写保护
HOLD:低电平时暂停
CLK:时钟信号

这里芯片是用3.3V的:



截图202510131949464097.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:52 | 显示全部楼层
接下来学习程序的编写:


先看好时序图:

我觉得没有单总线的18B20 那么清晰,有点乱:

截图202510131951585492.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:54 | 显示全部楼层
1.SPI的IO口初始化
2.SPI读取一个字节(MSB模式)
3.SPI写入一个字节

我们写个模式0CPOL=0   CPHA=0)的程序:



截图202510131953079996.jpg
截图202510131954065336.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:55 | 显示全部楼层
先明确引脚:



//------------------------------引脚定义------------------------------
#define CS    P22
#define MISO  P24
#define WP    P53
#define MOSI  P23
#define SCLK  P25



截图202510131954429323.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:56 | 显示全部楼层


最关键是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;   //再返回去循环第二位
               
        }

}


u8  SPI_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;



}


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 19:57 | 显示全部楼层
看看主函数:


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)                //死循环
        {
                u8  ID;
               
                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
               


                       
        }
}


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2025-10-13 19:39:49
已绑定手机

2

主题

254

回帖

738

积分

高级会员

积分
738
发表于 昨天 20:00 | 显示全部楼层
当然,看着冲哥写,跟着冲哥写,就容易


离开视频,真正自己对照时序图,能写出来并且调通,上机实验,能得到正确结果

那才是真的学会了!

好了,spi 就简单先到这里,其实还没完...................
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-14 08:12 , Processed in 0.122279 second(s), 86 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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