您的位置 首页 > 数码极客

proteus芯片如何编写程序、proteus怎么编写程序并编译…

1. 基于proteus的51单片机开发实例28-SPI总线的读写

1.1. 实验目的


图1 SPI串行总线的读写


在之前的实例中,我们已经学习了RS-232串行总线的读写,I2C总线的读写,本实例中,我们将要学习SPI总线的读写。本实例学完后,我们就全部学习了单片机系统最常用的三种串行总线:串口、I2C、SPI。

1.2. 设计思路

本例通过51单片机连接控制SPI总线器件X5045,使用SPI总线通信协议对X5045进行数据读写,并把写入的数据和读出的数据分别通过51单片机P0和P2口连接的8个LED显示出来,用以对比写入和读出的数据是否相同。

1.3. 基础知识

我们之前学过的RS-232串口属于异步串行接口,而SPI总线属于同步串行接口。SPI串行通信在单片机系统中有着广泛应用。

单片机与RS-232串口通信时,需要RXD(数据接收)和TXD(数据发送)两根线。

单片机与I2C串口通信时,需要SCL(总线时钟)和SDA(数据收发)两根线。

单片机与SPI串口通信时,需要SCK(总线时钟)、MISO(主机接收、从机发送)和MOSI(主机发送、从机接收)三根线。

下面我们结合X5045来了解SPI的基础知识。

X5045主要功能:单片机上电复位控制,看门狗定时器,降压管理,写保护功能的EEPROM数据存储器。

下图是x5045的引脚图。

图2 X5045引脚图


下图是X5045内部结构图。

图3 X5045内部结构


下图是X5045引脚功能说明。

图4 X5045引脚功能


图5 X5045引脚功能(续)


本实例我们主要通过X5045来了解SPI串行总线,所以对X5045的其它功能留待后续实例讲解。

X5045与单片机之间的串口通信,必须在严格的指令控制下进行。X5045的控制是通过其内部的一个8位指令寄存器进行。它可以通过SI引脚访问,数据在SCK的上升沿由同步时钟脉冲控制输入。在整个X5045工作期间,片选端口CS必须保持低电平,写保护引脚WP必须保持高电平。

X5045一共有6条操作指令。如下图所示。所有指令、地址、数据都是以高位在前的方式传送。输入的数据在CS变为低电平之后的SCK第一个上升沿被采用。


图6 X5045指令


向存储器写数据协议:

首先CS置低电平以选中芯片,然后写入WREN(写允许)指令,接着将CS拉到高电平,然后再次将CS拉到低电平,随后写入WRITE指令并跟随欲写入的8位地址。WRITE指令的第3位用于确定存储器的上半区和下半区。如果没有在WREN和WRITE两个指令之间将CS变为高电平,WRITE指令将被忽略,最后需要将CS变为高电平。

从存储器读数据协议:

首先将CS拉低以选中芯片,然后写入READ(读出)指令,跟着写入欲读出数据的8位地址。READ指令的第3位用以确定存储器的上半区和下半区。在读操作指令码发送完毕后,所选中地址单元的数据将通过SO引脚送出,最后还需要将CS拉到高电平。

1.4. 电路设计

本实例电路图如图1所示。单片机P3口连接X5045。同时单片机的P0口和P2口分别连接8个LED,用以指示写入和读出的数据是否一致。

1.5. 程序设计

本实例程序代码如下。由于51单片机没有内置SPI模块,所以本例中我们仍然使用模拟SPI时序的方法实现SPI总线的读、写操作。

#include<reg51.h> #include<in; sbit SCK=P3^3; //SCK引脚定义 sbit SI=P3^4; //SI引脚定义 sbit SO=P3^5; //SO引脚定义 sbit CS=P3^6; //CS引脚定义 #define WREN 0x06 //写使能锁存器允许 #define WRDI 0x04 //写使能锁存器禁止 #define WRSR 0x01 //写状态寄存器 #define READ 0x03 //读数据 #define WRITE 0x02 //写数据 //延时1ms void delay1ms(); //延时 Counter*1ms void delaynms(unsigned int Counter); //从当前地址读数据 unsigned char ReadCurrent(void); //向当前地址写数据 void WriteCurrent(unsigned char WriteData); //写状态寄存器 void WriteSR(unsigned char RegistData); //写数据到指定地址 void WriteSet(unsigned char Writedata,unsigned char WriteAddr); //从指定地址读数据 unsigned char ReadSet(unsigned char ReadAddr); //看门狗喂狗 void WatchDog(void); // void main(void) { unsigned char ucWriteDataTmp=1,ucReadDataTmp; P0=0xff; P0=0x00; WriteSR(0x12); //写状态寄存器:看门狗溢出时间600ms,没有写保护 delaynms(10); //x5045写入周期约为10ms while(1) { WatchDog(); //喂狗 P0=ucWriteDataTmp;//在P0口指示要写入的数据 WriteSet(ucWriteDataTmp,0x10); //向指定地址写入数据 delaynms(10); //x5045写入周期约为10ms ucReadDataTmp=ReadSet(0x10); //从指定地址读出数据 P2=ucReadDataTmp;//在p2口指示读出的数据 WatchDog(); //喂狗 delaynms(400); //延时一会,有时间看到LED显示的数值 ucWriteDataTmp++;//写入的数据+1 } } //延时1ms void delay1ms() { unsigned char i,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; } //延时若干ms void delaynms(unsigned int Counter) { unsigned int i; for(i=0;i<Counter;i++) delay1ms(); } //读当前地址数据 unsigned char ReadCurrent(void) { unsigned char i; unsigned char ReadTmp=0x00; SCK=1; //SCK拉高 for(i = 0; i < 8; i++)//一个字节8位,循环8次 { SCK=1; SCK=0; //SCK下降沿时输出数据 ReadTmp<<=1; //接收的数据是最高位 ReadTmp|=(unsigned char)SO; //读出SO上的数据 } return(ReadTmp); //返回读出的数据 } //写数据到当前地址 void WriteCurrent(unsigned char WriteData) { unsigned char i; SCK=0; //SCK拉低 for(i = 0; i < 8; i++) // 一个字节8位,循环写入 { SI=(bit)(WriteData&0x80); //取所写数据最高位,送到SI //传送顺序是高位在前 SCK=0; SCK=1; //SCK上升沿时,写入数据 WriteData<<=1; //数据左移,始终保持发送最高位 } } // void WriteSR(unsigned char RegistData) { CS=0; //CS拉低,选中芯片 WriteCurrent(WREN); //写使能锁存器允许 CS=1; //CS拉高 CS=0; //CS拉低,否则后面写指令会被忽略 WriteCurrent(WRSR); //写状态寄存器 WriteCurrent(RegistData); //写入新设置的状态 CS=1; //CS拉高 } // void WriteSet(unsigned char Writedata,unsigned char WriteAddr) { SCK=0; //SCK拉低 CS=0; //CS拉低,选中芯片 WriteCurrent(WREN); //写使能锁存器允许 CS=1; //CS拉高 CS=0; //再次拉低CS,否则写数据指令会被忽略 WriteCurrent(WRITE); //写指令 WriteCurrent(WriteAddr); //写入指定地址 WriteCurrent(Writedata); //写入数据 CS=1; //CS拉高 SCK=0; //SCK拉低 } //从指定地址读数据 unsigned char ReadSet(unsigned char ReadAddr) { unsigned char ReadData; SCK=0; //SCK置低 CS=0; //CS拉低,选中芯片 WriteCurrent(READ); //开始读操作 WriteCurrent(ReadAddr); //指定读数据的地址 ReadData=ReadCurrent(); //读出数据 CS=1; //CS拉高 SCK=0; //SCK拉低 return ReadData; //返回读出的数据 } //看门狗狗喂狗 void WatchDog(void) { CS=1; //CS拉高 CS=0; //CS拉低,CS一个下降沿操作喂狗 CS=1; //CS拉高 }

1.6. 实例仿真

编写程序代码,编译生成HEX文件,将HEX文件装载到proteus电路的单片机中,开始仿真,连接在P0口和P2口的两组发光二极管,看看他们显示的是否一致。

1.7. 总结

通过本例,我们学习了I2C总线的原理、电路设计、编程方法。至此,我们已经学习了三种串行通信:RS-232串口通信,I2C串行通信,SPI串行通信,大家可以对比这三种串行通信的异同。

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“proteus芯片如何编写程序,proteus怎么编写程序并编译,proteus在哪里编写程序,proteus怎么编写程序,proteus自带编译器编写程序”边界阅读