wuzhengmin 发表于 2025-10-14 09:55:40

实际上,我们的住函数有个缺陷:


我们尝试多读几次芯片的ID:

结果看下图:


wuzhengmin 发表于 2025-10-14 09:58:08

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();
                        SPI_Init();   //SPI初始化
                        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
               


                       
        }
}

是不是发现出差啦?‘

其实主要的初始化问题:

我们把主函数改一下:

wuzhengmin 发表于 2025-10-14 10:00:41

我发现每次读取之前,一定要重新初始化一次,才能正确的得到ID号:
SPI_Init();   //SPI初始化

看运行结果:





这样就能多次读取,每次都读对

baocong2023 发表于 2025-10-15 15:23:33

wuzhengmin 发表于 2025-8-12 10:04
为什么要搞不停电下载?就是要像STC89C52RC用在清翔C51实验板上那样,下载的时候不用按任何按键!

方便我 ...

楼主这个mdk背景配色 不敢恭维,感觉刺眼睛{:zhuakuang:}

wuzhengmin 发表于 2025-10-15 15:37:36

baocong2023 发表于 2025-10-15 15:23
楼主这个mdk背景配色 不敢恭维,感觉刺眼睛

是啊,我也在找好一点的啊,还没有找到啊

wuzhengmin 发表于 2025-10-15 15:42:37

今天我们继续学习   第二十八集:硬件SPI读写FLASH


其实这里容易产生似懂非懂的感觉:

1.SPI简介SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI是一种高口速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。 这种接口,看上去好简单:

产生时钟的一侧称为主机,另一侧称为从机。同一时间只有一个主机,但是可以有多个从机。
SPI总线包括4条逻辑线,定义如下:
MISO:Master input slave output 主机输入,从机输出(数据来自从机);MOSI:Masteroutput slave input主机输出,从机输入(数据来自主机);SCLK:Serial Clock串行时钟信号,由主机产生发送给从机;SS Slave Select 片选信号,由主机发送以控制与哪个从机通信,通常是低电平有效信号

wuzhengmin 发表于 2025-10-15 15:45:28

多数是单主多从,由SS的电平决定每一时刻和谁通信
通信方式和主多从,看下图:


wuzhengmin 发表于 2025-10-15 15:47:21

SPI数据模式:时钟极性(CKP/CPOL)根据硬件制造商的命名规则不同,时钟极性通常写为CKP或CPOLCKOL可以配置为1或0。这意味着可以根据需要将时钟的默认状态(IDLE)设置为高或低。当然具体的配置必须参考设备的数据手册正确设置CKP=0:时钟空闲IDLE为低电平 0;CKP=.1:时钟空闲IDLE为高电平·1;时钟相位(CKE/CPHA)
顾名思义,时钟相位/边沿,也就是采集数据时是在时钟信号的具体相位或者边沿;CPHA = 0:在时钟信号SCK的第一个跳变沿采样;CPHA= 1:在时钟信号SCK的第二个跳变沿采样;时钟极性和相位共同决定读取数据的方式,比如信号上升沿读取数据还是信号下降沿读取数据;



wuzhengmin 发表于 2025-10-15 15:50:45

时钟极性控制和时钟相位控制:


下面是试验箱引脚硬件连接:


wuzhengmin 发表于 2025-10-15 15:53:22

1.硬件链接CS:低电平有效DI/DO:数据输入输出端WP:低电平写保护HOLD:低电平时暂停CLK:时钟信号
有个问题要小心:
这个存储芯片是3.3V 我们STC32G12K128是5V
不同工作电源电压,要千万小心,很容易出问题的:
看图:


页: 11 12 13 14 15 16 17 18 19 20 [21] 22 23 24 25 26 27 28 29 30
查看完整版本: 第一次:环境的创立 | 送实验箱