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

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

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 15:56 | 显示全部楼层
下面是重点研究的时序图:


1.SPI的IO口初始化
2.SPI读取一个字节(MSB模式)
3.SPI写入一个字节
这3个函数都是看着时序图来编写:


截图202510151554548095.jpg
截图202510151555168546.jpg
截图202510151556172201.jpg
截图202510151556295406.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 16:00 | 显示全部楼层
跟着冲哥,慢慢来:


  1. void SPI_Init(void)                                //初始化
  2.         {
  3.                 CS           = 1;                                        //不选中该器件
  4.                 MISO  = 1;                                        //       
  5.                 WP          = 1;                       
  6.                 MOSI  = 1;       
  7.                 SCLK  = 0;                                        //spi模式0,sclk初始化为低电平       
  8.         }
  9.         void SPI_WriteByte(u8 dat)                //写入一个字节
  10.         {
  11.                 u8 i;
  12.                 for( i=0;i<8;i++ )
  13.                 {
  14.                         if( dat & 0x80 )
  15.                                 MOSI = 1;
  16.                         else
  17.                                 MOSI = 0;
  18.                         SCLK = 1;                                //下降沿
  19.                         SCLK = 0;
  20.                         dat <<=1;
  21.                 }
  22.         }
  23.         u8 SPI_ReadByte(void)                        //读取一个字节
  24.         {
  25.                 u8 i;
  26.                 u8 dat=0;
  27.                
  28.                 for( i=0;i<8;i++ )
  29.                 {
  30.                         dat<<=1;
  31.                        
  32.                         SCLK = 1;                               
  33.                         if( MISO )                                //从机往主机发送数据的引脚
  34.                                 dat |= 1;
  35.         //                else
  36.         //                        dat |= 0;
  37.                         SCLK = 0;
  38.                 }
  39.                
  40.                 return dat;
  41.         }
复制代码
这是软件模拟的情况,能读出存储芯片的ID:

截图202510151600093962.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 16:02 | 显示全部楼层
接着就换硬件的SPI:


先看寄存器:


首先是引脚选择,我们还是配成01 P22 P23 P24 P25


截图202510151601572640.jpg
截图202510151602093145.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 16:04 | 显示全部楼层
串口1控制寄存器(SCON)我们要选择模式0,注意第四位REN必须配置为1才能接受数据。



截图202510151603253433.jpg
截图202510151604196623.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 16:06 | 显示全部楼层
硬件SPI 对应的3个函数:


  1. void SPI_Init(void)                                //初始化
  2.         {
  3.                 P_SW1 &= 0XF3;                //1111 0011                P_SW1功能寄存器,引脚切换选择 B3B2位决定4种引脚配置
  4.                 P_SW1 |= 0X04;                //0000 0100     我们要选P22P23P24P25,先要把B3B2清零,才能改写为01
  5.                                                         //清零用P_SW1 &= 1111 0011 B3B2改写为01:P_SW1 |= 0000 0100
  6.                
  7.                 SPCTL = 0X90;                //SPI控制寄存器SPCTL,SPCTL是最核心的模式配置,第一位取1:忽略引脚功能,
  8.                                     //使用MSTR确定器件是主机还是从机,第二位是使能位,第三位DORD:SPI数据位发
  9.                                                         //送/接收的顺序,0:先发送/接收数据的高位(MSB)1:先发送/接收数据的低
  10.                                                         //位(LSB).第四位MSTR:器件主/从模式选择位:设置主机模式
  11.                                                         //若 SSIG=0,则 SS 管脚必须为高电平且设置 MSTR 为1若 SSIG=1,则只需要设置
  12.                                                         //MSTR 为 1(忽略 SS 管脚的电平)设置从机模式:
  13.                                                         //若 SSIG=0,则 SS 管脚必须为低电平(与 MSTR 位无关)若 SSIG=1,则只需要设
  14.                                                         //置 MSTR 为 0(忽略 SS 管脚的电平)第3位CPOL设置时钟极性和时钟相位控制
  15.                                                         //CPOL:SPI 时钟极性控制,0:SCLK 空闲时为低电平,SCLK 的前时钟沿为上升沿,
  16.                                                         //后时钟沿为下降沿1:SCLK 空闲时为高电平,SCLK 的前时钟沿为下降沿,后时钟沿
  17.                                                         //为上升沿  第2位CPHA:SPI 时钟相位控制,0:数据 SS 管脚为低电平驱动第一位数
  18.                                                         //据并在 SCLK 的后时钟沿改变数据,前时钟沿采样数据(必须SSIG=0),1:数据在
  19.                                                         //SCLK 的前时钟沿驱动,后时钟沿采样.最后1和0位是时钟频率选择
  20.                
  21.                
  22.                 SPCTL |= 0X40;     //只有1个存储芯片,配主从模式,第一位和第四位取1,先不使能,MSB方式读取:得
  23.                                                    //0x90,配置完成,最后再使能SPI:SPCTL |= 0X40(第二位置1)
  24.                
  25.                 SCLK = 0;                        //时钟引脚初始化spi模式0,sclk初始化为低电平       
  26.                
  27.                 SPIF = 1;                        //SPSTAT是状态寄存器,SPIF清空标志位要置1。当发送/接收完成 1 字节的数据后,
  28.                                                         //硬件自动将此位置 1,并向 CPU 提出中断请求。当 SSIG 位被设置为0 时,由于
  29.                                                         //SS管脚电平的变化而使得设备的主/从模式发生改变时,此标志位也会被硬件自动
  30.                                                         //置1,以标志设备模式发生变化。注意:此标志位必须用户通过软件方式向此位写
  31.                                                         //1 进行清零。SPIF不等于0,发送/接受就结束了,SPIF读到0表示正在读写,读到
  32.                                                         //1表示完成
  33.                 WCOL = 1;           //WCOL:SPI写冲突标志位。当SPI在进行数据传输的过程中写SPDAT寄存器时,硬件
  34.                                                         //将此位置1.注意:此标志位必须用户通过软件方式向此位写 1 进行清零。
  35.                                                         //读取和写入完成之后都要清空SPIF和WCOL(置1)
  36.         }
  37.         void SPI_WriteByte(u8 dat)                //写入一个字节
  38.         {
  39.                 SPDAT = dat;       //SPI 数据寄存器(SPDAT),SPI 发送/接收数据缓冲器。
  40.                 while(SPIF == 0);
  41.                 SPIF = 1;          //每次读取写入完成后都要清空状态寄存器标志位
  42.                 WCOL = 1;                   //每次读取写入完成后都要清空状态寄存器标志位
  43.         }
  44.         u8 SPI_ReadByte(void)                        //读取一个字节
  45.         {
  46.                 SPDAT = 0XFF;       //SPI 数据寄存器(SPDAT),SPI 发送/接收数据缓冲器。
  47.                                                         //这里发送一个字节,主要是为了产生8位时钟脉冲,没有脉冲无法读数据
  48.                 while(SPIF == 0);
  49.                 SPIF = 1;           //每次读取写入完成后都要清空状态寄存器标志位
  50.                 WCOL = 1;                    //每次读取写入完成后都要清空状态寄存器标志位
  51.                 return SPDAT;
  52.         }
复制代码
我已经注释的很详细了,方便以后查看..............
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 16:09 | 显示全部楼层
最后是USART_SPI


串口1同步模式控制寄存器1(USARTCR1)


这种串口配置,寄存器比较多,一开始容易晕菜:


截图202510151608433995.jpg
截图202510151608575542.jpg
截图202510151609092879.jpg
截图202510151609218813.jpg
截图202510151609321234.jpg
截图202510151609431066.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:42
  • 最近打卡:2025-10-15 15:37:36
已绑定手机

2

主题

271

回帖

780

积分

高级会员

积分
780
发表于 昨天 16:13 | 显示全部楼层
不过,其实还好,有些我们不要管它..........


串口1同步SPI的函数如下:

  1. void SPI_Init(void)                                //初始化USART_SPI寄存器
  2.         {
  3.                 P_SW3 &= 0XF3;                //1111 0011                引脚选择  P_SW3 第3位第2位选01模式(对应引脚P22--P25)
  4.                 P_SW3 |= 0X04;                //0000 0100
  5.                
  6.                 SCON = 0x10;       //串口1控制寄存器(SCON)模式0同步移位串行方式 REN位取1
  7.                
  8.                 USARTCR1=0x10;    //串口1同步模式控制寄存器1(USARTCR1)DORD:SPI 模式数据位发送/接收的顺序
  9.                                                   //0:先发送/接收数据的高位(MSB)
  10.                                                   //1:先发送/接收数据的低位(LSB)
  11.                 USARTCR4=0x00;    //串口1同步模式控制寄存器4(USARTCR4),SPI 模式时钟选择,选最慢
  12.                 USARTCR1|=0x08;  //1:使能 SPI 功能
  13.         }
  14.         void SPI_WriteByte(u8 dat)                //写入一个字节
  15.         {
  16.                 TI = 0;          //清标志位
  17.                 SBUF = dat;
  18.                 while(!TI);
  19.         }
  20.         u8 SPI_ReadByte(void)                        //读取一个字节
  21.         {
  22.                 TI = 0;        //清标志位
  23.                 SBUF = 0X00;   //产生8个时钟脉冲信号用来传递数据
  24.                 while(!TI);
  25.                 return SBUF;
  26.         }       
复制代码
也是尽可能详细的注释,方便以后查询.....................

运行结果也很顺利 ,感觉真的是好像七窍通了六窍,不是真的懂了,只是做了一遍,嘻嘻!好了,今天就这样啦!
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-10-16 01:17 , Processed in 0.144281 second(s), 77 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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