运用4个普通IO口模拟SPI程序等
4根IO口线驱动1602(带PWM调光)

4根IO口线驱动1602(带PWM调光)呵呵,不用我说你们也知道为什么只需要4根线:因为咱用了74hc595啊!因为74HC595最近我手里一抓一大把。
但是STC的单片机IO口紧缺。
就算使用4线驱动模式也要8个IO(还要算上背光PWM)。
这一次我几乎做到了他的一半。
如果不用PWM的话。
大概只需要3个IO,如果需要PWM就四个罗。
MCU当然是老掉牙的死特惨89C52罗~画原理图实在是不方便。
就不画了。
另外求酷~也可以在595后面级联类似三极管开关……继电器之类的玩意。
当然友情提醒,别超过4个595.否则速度会慢的可怕。
我现在1个595.写1602都可以丢掉延时函数了。
这一次硬件设计的比较简单,但是IO全反了。
所以需要占用额外的CPU时间修正,但是毕竟方便洞洞板嘛。
还有大家别看到我给A和B赋了好几次值而去“优化”代码。
如果您“优化”的话,那么就根本驱动不起来,因为51的加法减法乘除都要经过ACC和B,如果不去重新赋值的话,那么就会发生改变的现象。
不过我这种位寻址软件修正可比那种xx=xx & xx的效率高多了。
如果我这么写的话。
恐怕刷一个屏幕没1秒下不来啊。
12T的51就这个速度……不过这一次焊板子实在是太仓促了。
对比度电位器焊在液晶下面,结果初始化成功了显示两排方块。
晕了半天。
调试半天还是没用。
后来捅了一下背面就好了……晕……!上代码:#include <stc89c5x.h>//STC89C52//串行驱动1602,powered by 595#define LCD1602_BACKLIGHT P1_3//背光#define LCD1602_SDA P1_0//数据输入#define LCD1602_SCK P1_1//移位时钟,SHCP,11pin#define LCD1602_SCL P1_2//锁存时钟,STCP,12pin/** 硬件连接:* 74HC595 Q7 - 1602 RS* GND - 1602 RW(595没有输入功能,所以判定忙只能靠延时,另外就是MCU的速度比较的慢。
使用MCU的GPIO模拟SPI

使用MCU的GPIO模拟SPI在树莓派等单片机(MCU)上,可以使用GPIO模拟SPI(串行外设接口)来与其他设备进行通信。
SPI是一种同步串行数据传输协议,通常用于连接MCU和传感器、显示器、存储器等外设。
以下是使用MCU的GPIO模拟SPI的详细步骤。
1.了解SPI的基本原理:SPI使用四根信号线进行通信,包括时钟(SCLK)、主机输出从机输入(MOSI)、主机输入从机输出(MISO)和片选(SS)。
-SCLK:时钟信号,由主机产生,用于同步数据传输。
-MOSI:主机输出从机输入,主机将数据发送到从机。
-MISO:主机输入从机输出,从机将数据发送到主机。
-SS:片选信号,用于选择从机。
2.确定所需GPIO引脚:根据所连接的设备的要求,选择合适的GPIO引脚作为SCLK、MOSI、MISO和SS。
3. 配置GPIO引脚:在MCU上,使用相应的编程语言和库函数来配置GPIO引脚。
例如,在树莓派上使用Python编程,可以使用RPi.GPIO库进行配置。
4.编写SPI传输函数:编写一个函数来模拟SPI传输。
该函数应包括以下步骤:a.设置SS为低电平,选中从机设备。
b.发送数据比特串:逐位发送MOSI数据,同时接收并保存MISO数据。
c.设置SS为高电平,取消从机设备的选中。
假设我们要发送8位数据,可以使用以下Python代码实现SPI传输函数:```pythonimport RPi.GPIO as GPIOdef spi_transfer(data):GPIO.output(SS, GPIO.LOW) # 选中从机received_data = 0for bit in range(7, -1, -1): # 逐位传输数据#发送MOSI数据GPIO.output(MOSI, (data >> bit) & 0x01)#接收并保存MISO数据received_bit = GPIO.input(MISO)received_data = (received_data << 1) , received_bit#在SCLK上升沿发送和接收数据GPIO.output(SCLK, GPIO.HIGH)GPIO.output(SCLK, GPIO.LOW)GPIO.output(SS, GPIO.HIGH) # 取消从机选中return received_data```5. 通过调用SPI传输函数与从机通信:在应用程序中,根据需要调用SPI传输函数。
用GPIO模拟SPI协议的实现

一SPI协议概括SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。
是Motorola首先在其MC68HCXX系列处理器上定义的。
SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,比如AT91RM9200.SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。
也是所有基于SPI的设备共有的,它们是SDI (数据输入),SDO(数据输出),SCK(时钟),CS(片选)。
(1)SDO –主设备数据输出,从设备数据输入(2)SDI –主设备数据输入,从设备数据输出(3)SCLK –时钟信号,由主设备产生(4)CS –从设备使能信号,由主设备控制其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效。
这就允许在同一总线上连接多个SPI设备成为可能。
接下来就负责通讯的3根线了。
通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。
这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。
数据输出通过SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。
完成一位数据传输,输入也使用同样原理。
这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。
要注意的是,SCK信号线只由主设备控制,从设备不能控制信号线。
同样,在一个基于SPI的设备中,至少有一个主控设备。
怎样使用IO口模拟SPI时序访问W5100

怎样使用IO口模拟SPI时序访问W5100 2008-2-23 23:31:48摘自浩然电子:http:很多客户为了简化硬件设计,在对速度要求不高的情况下,常常采用SPI 总线访问W5100。
这里根据浩然电子EVB-W5100/MCS51评估板,给出一个用MCS51的I/O口模拟SPI总线访问的C程序例子。
该程序经过修改可以移植到任何单片机系统中。
/*************定义SPI的引脚端口**************/sbit SCS =P3^3;/*定义SPI的片选信号端口*/sbit SCLK =P2^3;/*定义SPI的时钟信号端口*/sbitMISO =P2^6;/*定义SPI的MISO端口*/sbit MOSI =P2^4;/*定义SPI的MOSI端口*/#define SET_SCS SCS=1;#define RESET_SCS SCS=0;#define SET_SCLK SCLK=1;#define RESET_SCLK SCLK=0;#define SET_MOSI MOSI=1;#defineRESET_MOSI MOSI=0;/***************************************************************** ***IO_Config主要是对IO口进行初始化设置根据不同的MCU添加相应的代码,实现下面注释部分的功能***************************************************************** ***/voidIO_Config (void ){/*定义SCS口为输出,初始化为高电平*/SET_SCS/*定义SCLK口为输出,初始化为低电平*/RESET_SCLK/*定义CPU的MOSI端口为输出, MISO端口为输入*/}/****************************************************************** **通过SPI总线输出一个字节***************************************************************** ***/void SPI_Out (unsigned chardat ){unsigned chari;for ( i = 0; i < 8; i++){if ( dat & 0x80 )SET_MOSIelseRESET_MOSISET_SCLK /*时钟上升*/dat <<= 1;RESET_SCLK /*时钟下降*/}}/***************************************************************** ***通过SPI向W5100写入数据输入参数:写入地址addr,写入的数据dat无返回参数***************************************************************** ***/voidWrite_W5100_SPI (unsigned intaddr,unsigned chardat ){RESET_SCS/* SPI的片选置低*//*输出的第一个字节为写命令*/SPI_Out ( 0xf0 );/*写命令*//*输出的第二个字节为地址高8位*/SPI_Out ( addr / 256 );/*地址高8位*//*输出的第三个字节为地址低8位*/SPI_Out ( addr );/*地址低8位*//*输出的第四个字节为写入的数据*/SPI_Out ( dat );SET_SCS /* SPI的片选置高*/}/****************************************************************** **通过SPI读取W5100的数据输入参数:读取地址addr,返回参数:读取的数据***************************************************************** ***/unsigned charRead_W5100_SPI (unsigned intaddr ){unsigned chari, j;RESET_SCS /* SPI的片选置低*//*输出的第一个字节为写命令*/SPI_Out ( 0x0f );/*读命令*//*输出的第二个字节为地址高8位*/SPI_Out ( addr / 256 );/*地址高8位*//*输出的第三个字节为地址低8位*/SPI_Out ( addr );/*地址低8位*//*输出一个空字节,读取一个字节的数据*/j=0;for( i = 0; i < 8; i++ ){ SET_SCLK/*时钟上升*/j <<= 1;if( MISO )j |= 0x01;RESET_SCLK /*时钟下降*/} SET_SCS/* SPI的片选置高电平*/returnj;}先调用IO_Config()函数对IO口进行初始化设置。
AVR单片机IO口模拟SPI四种模式的程序

时钟相位(CPHA)和时钟极性(CPOL)的不同组合使得SPI传输有了4种方式如果CPOL =0,SCK 引脚在空闲状态保持低电平;如果CPOL =1,SCK 引脚在空闲状态保持高电平时序图如下://IO端口定义#define SPI_SCK PC0#define SPI_MOSI PC1#define SPI_MISO PC2#define SPI_DDR DDRC#define SPI_PORT PROTC#define SPI_PIN PINC//端口操作符定义#define SCK_SET SPI_PORT|=_BV(SPI_SCK)#define SCK_CLR SPI_PORT&=~_BV(SPI-SCK)#define MOSI_SET SPI_PORT|=_BV(SPI_MOSI)#define MOSI_CLR SPI_PORT&=~_BV(SPI_MOSI)#define MISO_PIN PINC&_BV(SPI_MISO)#define DELAY_BUS //如需要延时,用延时函数替代此符号//模式1:CPOL=1 CPHA=1void spi_init(void){SCK_SET;SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);}uint8_t spi_readwrite_byte(uint8_t data){uint8_t i,ret=0;for(i=0;i<8;i++){//下降沿模拟if(data&0x80)//设置输出MOSI_SET;elseMOSI_CLR;SCK_CRL;//SCK产生下降沿DELAY_BUS;//上升沿模拟ret<<=1;if(MISO_PIN)//读数据ret|=1;SCK_SET; //SCK产生上升沿data<<=1;DELAY_BUS;}return ret;}//模式2:CPOL=0 CPHA=1void spi_init(void){SCK_CLR;SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);}uint8_t spi_readwrite_byte(uint8_t data) {uint8_t i,ret=0;for(i=0;i<8;i++){//上升沿模拟if(data&0x80)//设置输出MOSI_SET;elseMOSI_CLR;SCK_SET;//SCK产生上升沿DELAY_BUS;//下降沿模拟ret<<=1;if(MISO_PIN)//读数据ret|=1;SCK_CLR; //SCK产生下降沿data<<=1;DELAY_BUS;}return ret;}//模式3:CPOL=1 CPHA=0void spi_init(void){SCK_SET;SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);}uint8_t spi_readwrite_byte(uint8_t data) {uint8_t i,ret=0;//设置好输出口if(data&0x80)MOSI_SET;elseMOSI_CLR;for(i=0;i<8;i++){DELAY_BUS;//下降沿模拟ret<<=1;if(MISO_PIN)//读数据ret|=1;SCK_CRL;//SCK产生下降沿DELAY_BUS;//上升沿模拟data<<=1;if(data&0x80)//设置输出MOSI_SET;elseMOSI_CLR;SCK_SET; //SCK产生上升沿}return ret;}//模式4:CPOL=0 CPHA=0void spi_init(void){SCK_CLR;SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);}uint8_t spi_readwrite_byte(uint8_t data) {uint8_t i,ret=0;//设置好输出口if(data&0x80)MOSI_SET;elseMOSI_CLR;for(i=0;i<8;i++){DELAY_BUS;//上升沿模拟ret<<=1;if(MISO_PIN)//读数据ret|=1;SCK_SET;//SCK产生上升沿DELAY_BUS;//下降沿模拟data<<=1;if(data&0x80)//设置输出 MOSI_SET;elseMOSI_CLR;SCK_CLR; //SCK产生下降沿 }return ret;}。
几种常用的模拟SPI读写一体化模块(C51)

几种常用的模拟SPI读写一体化模块(C51)几种常用的模拟SPI读写一体化模块(C51)原文:说明:SPI接口有一个特点,即在时钟SCK的上升沿打入数据MOSI,在下降沿读入数据MISO.片选信号CS有正负区别.在硬件上MOSI与MISO是可以短路变为SIO可读写IO的.故SPI可为(不包括CS)三线(SCK,MOSI,MISO)协议,两线(SCK,SIO)协议再者,SPI一般为双向同时高速收发数据的,方向由时钟SCK的跳变沿决定。
根据以上所述,模拟SPI读写模块编制成为一体化模块是必要的。
而且调用规则只需注意读数据时要写入0xff即可。
非常方便好用。
例如:res = SpiReadWrite(val);//模块写SpiReadWrite(0xff);//模块读对于具体器件,由于涉及到命令、地址及数据等,故一个完整的SPI读或写操作可能需要几个模拟SPI读写一体化模块来完成。
所以一般完整的SPI读或写操作需以下函数组合完成void SpiOpen(void); //打开片选 CS=0或CS=1void SpiClose(void); //关闭片选 CS=1或CS=0unsigned char SpiReadWrite(val); //模拟SPI读写一体化模块void SpiWriteEnable(void); //使能写操作void SpiWriteD ISA ble(void); //禁止写操作unsigned char SpiReadStatus(void); //读状态void SpiWriteStatus(unsigned char val); //写状态void SpiWriteWait(void); //等待写入完成void SpiWriteByte(unsigned int addr, unsigned char val);//写一个字节void SpiWriteWord(unsigned char addr, unsigned int val);//写一个字unsigned char SpiReadByte(unsigned int addr); //读一个字节unsigned int SpiReadWord(unsigned char addr); //读一个字/*----------------------------------------------------------------------------/*-----------------------------------------------例:X5045模拟SPI读写一体化模块PTR905模拟SPI读写一体化模块------------------------------------------------*unsigned char SpiReadWrite(unsigned char val){unsigned char i;ACC = val;for (i = 8; i > 0; i --){CY = MISO;//取数据SO_rlca_();//存数据ACC.0读数据ACC.7同时进行MOSI = CY;//送数据SISCK = 1;//上升沿打入数据_nop_();//延时SCK = 0;//下降沿读入数据}return ACC;}/*----------------------------------------------- 例:X5045模拟SPI读写一体化模块ISD4004模拟SPI读写一体化模块------------------------------------------------* unsigned char SpiReadWrite(unsigned char val) {unsigned char i;ACC = val;for (i = 8; i > 0; i --){SCK = 0;//下降沿读入数据_nop_();//延时CY = MISO;//取数据SO_rlca_();//存数据ACC.0读数据ACC.7同时进行MOSI = CY;//送数据SI_nop_();//延时SCK = 1;//上升沿打入数据MOSI = 1;//释放总线SI}return ACC;}/*----------------------------------------------- 例:AT93C46模拟SPI读写模块------------------------------------------------* sbit ACC_7 = ACC^7;unsigned char SpiReadWrite(unsigned char val) {unsigned char i;ACC = val;for (i = 8; i > 0; i --){CY = ACC_7;//读数据ACC.7MOSI = CY;//送数据SISCK = 1;//上升沿打入数据CY = MISO;//取数据SO_rlca_();//存数据ACC.0SCK = 0;//下降沿}return ACC;}。
IO口模拟SPI主从机例程

IO口模拟spi主从机通讯例程下面这两幅图是,关于SPI数据读取或发送的时序图。
1、主机io口模拟spi通讯例程//**spi io 口初始化**//void SPI_init(void){gpio_configure_fpin(SPI_MISO, IO_TYPE_INPUT);//配置成输入模式gpio_configure_fpin(SPI_MOSI, IO_OUTPUT_1);//配置成输出模式gpio_configure_fpin(SPI_SCK, IO_OUTPUT_1); //配置成输出模式gpio_configure_fpin(SPI_CS, IO_OUTPUT_1); //配置成输出模式clr_spi_GPIO(SPI_SCK);//拉低SPI_SCKset_spi_GPIO(SPI_CS);//拉高SPI_SCKclr_spi_GPIO(SPI_MOSI);//拉低SPI_MOSI}//**主机spi读取一字节api**//unsigned char SPI_ReadByte(void){unsigned char i,rByte=0;clr_spi_GPIO(SPI_CS);for(i=0;i<8;i++){clr_spi_GPIO(SPI_SCK);//clr_spi_sck;delay_us(3);rByte<<=1;if(MISO_is_status())////M16 MISO---PB6rByte|=1;set_spi_GPIO(SPI_SCK);//set_spi_sck;delay_us(3);}clr_spi_GPIO(SPI_SCK);set_spi_GPIO(SPI_CS);return rByte;}//** 读取miso 的电平**//char MISO_is_status(void){if(red_spi_GPIO(SPI_MISO))//return 1;elsereturn 0;}//**主机spi写入一字节api**//void SPI_WriteByte(unsigned char wByte){unsigned char i;clr_spi_GPIO(SPI_CS);for(i=0;i<8;i++){clr_spi_GPIO(SPI_SCK);//delay_us(3);//if(wByte&0x80){set_spi_GPIO(SPI_MOSI);//}else{clr_spi_GPIO(SPI_MOSI);//}wByte=wByte<<1;set_spi_GPIO(SPI_SCK);//set_spi_sck;delay_us(3);//}clr_spi_GPIO(SPI_SCK);set_spi_GPIO(SPI_CS);}////////////////////////////////////////////////////////////////////////////////////注意,我写的主从机的io口对接如下主机io 从机ioSPI_MISO ------------------------- SPI_MISOSPI_MOSI --------------------------- SPI_MOSISPI_SCK --------------------------- SPI_SCKSPI_CS -------------------------- SPI_CS可能有的人对上面的io口对接的方式感到奇怪,请仔细看我对这几个io口做的初始化设置就可以明白。
IO口模拟SPI接口

IO口模拟SPI接口//头文件#include#include/*********************************************模拟SPI接口I/O定义*********************************************/sbit CS =P3^2; //片选信号 (输入)sbit SCK =P3^3; //时钟信号 (输入)sbit MISO=P3^4; //主站输入从站输出 (输出)sbit MOSI=P3^5; //主站输出从站输入 (输入)#define SET_CS() CS=1 //片选信号置高#define RESET_CS() CS=0 //片选信号置低#define SET_SCK() SCK=1 //时钟信号置高#define RESET_SCK() SCK=0 //时钟信号置低//自定义变量unsigned char spi_flag=0,SPI_Data=0;//自定义函数extern void Usart_Send(unsigned char Data);/************************************************************** **********程序描述:系统初始化程序*************************************************************** ****************/void System_Init(){//串口参数初始化SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1 TMOD|= 0x20; //定时器工作方式2PCON|= 0x80;TH1 = 0xF3; //baud*2 4800、数据位8、停止位1、效验位无(12M)TL1 = 0xF3;TR1 = 1; //允许定时器1计数ES = 1; //开串口中断*///定时器0初始化TMOD|= 0x01; //定时器工作方式1TH0 = 0xFC; //1msTL0 = 0x18;TR0 = 1; //允许定时器0计数ET0 = 1; //开定时器0中断IP=0x03; //设置定时器0中断高优先级//IT1=0; //低电平触发IT1=1; //下降沿触发//EX1=1; //外部中断1允许EA=1; //开总中断}/************************************************************** **********程序描述:模拟SPI通信主程序*************************************************************** ****************/main(){System_Init();while(1){/*if(MOSI==1)Usart_Send(0x01);elseUsart_Send(0x00);*/}}/************************************************************** **********程序描述:定时器0中断程序*************************************************************** ****************/void T0_inter(void) interrupt 1{TH0 = 0xFC; //1msTL0 = 0x18;if(CS==0){EX1=1;//Usart_Send(0xbb);}if(CS==1){EX1=0;//Usart_Send(SPI_Data);}}/************************************************************** **********程序描述:外部中断0服务程序*************************************************************** ****************/void ExINT1_Interrupt(void) interrupt 2 using 0{SPI_Data = SPI_Data<<1;if(MOSI==1){SPI_Data |= 0x01;//Usart_Send(0x01);}else{SPI_Data&= ~0x01;//Usart_Send(0x00); }spi_flag++;if(spi_flag==8){spi_flag=0;Usart_Send(SPI_Data); SPI_Data=0;}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
运用 4 个普通 I/O 口模拟 SPI 程序源代码
/******************************************************************** 函 数 名:uchar SpiReadWrite(uchar dat) 功 能:SPI 发送接收一个数据 说 明: 调 用: 入口参数: 出口参数: ***********************************************************************/ uchar SpiReadWrite(uchar dat) { uchar i,temp; temp=0; SCK=0; _nop_(); for(i=0;i<8;i++) { if(dat & 0x80) { MOSI=1; }
2、SPI 简介: 同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量 用在与 EEPROM、ADC、FLASH 和显示驱动器之类的慢速外设器件通信。
SPI(Serial Peripheral Interface)是一种串行同步通讯协议,由一个主设 备和一个或多个从设备组成,主设备启动一个与从设备的同步通讯,从而完成数 据的交换。通讯时,数据由 MOSI 输出,MISO 输入,数据在时钟的上升或下 降沿由 MOSI 输出,在紧接着的下降或上升沿由 MISO 读入,这样经过 8/16 次 时钟的改变,完成 8/16 位数据的传输。
编辑 删除
suyf
void ReadSpi(UINT8 command, UINT8* pValue)
积分:1
{
派别:
UINT8 idata i,k;
等级:------
来自:
// Enable SPI
CS=1;
delay_nops(1);
SCLK=0;
delay_nops(1);
CS=0;
// Send 8-bits Command to SPI
26. 27. * SPI 串 行 总 线 是 68 系 列 单 片 机 的 接 口, 具 有 节 约 IO 口, 减
少 连 接 线 等 一 些 特 点。 现 在 使 用 SPI 总 线 接 口 的 芯 片 越 来 越 多, 但 是 51 单 片 机 没 有 SPI 总 线, 所 以 需 要 用 IO 口 来 模 拟。 上 面 的 程 序 模 拟 了 一 个 通 用 的 SPI 总 线, 只 需 要 定 义 好 sck/si/so, 就 可 以 使 用 了。 28. 其 中 sck 是 串 行 时 钟 29. si 输 出 30. so 输 入 lxpkaka 的笔记 AT45DB041B 的模拟 SPI 程序 作者 lxpkaka 日期 2009-2-13 8:41:00
钟。读也是一样,
积分:416
写应该是 时钟——〉写数据——〉延时——〉时
派别:
钟。你延时的位置有点不对,另外,发送地址之后为什么要等那
等级:------ 么长时间?
来自:
我只看了读的程序。
2006-11-0 资料 邮件 7,11:06:53
【2 楼】 gan 我这里有 PIC18F6520 的程序你看看:
*************************/
ulong Read_SPI(uchar comm)
{
uchar j; ulong rbyte=0;
if(ATT_SIG==0)
{
SET7022_CS;
//使能 SPI
CLR7022_SCLK;
CLR7022_CS;
#asm("cli")
//关ORTB.5
#define ATT_SEL PORTB.6
#define ATT_REST PORTB.1
#define SET7022_Din PORTB|=(1<<2)
#define CLR7022_Din PORTB&=~(1<<2)
#define SET7022_SCLK PORTB|=(1<<4)
else MOSI=0; dat<<=1; SCK=1; _nop_(); _nop_(); _nop_(); _nop_(); temp<<=1; if(MISO)temp++; SCK=0; _nop_(); _nop_(); _nop_(); _nop_(); } return temp; }
ATT_CS=1;
ATT_SCLK=0;
ATT_CS=0;
comm = comm|0x80;
for( j=0;j<8;j++)
{
ATT_SCLK=1; //送时钟
if((comm>>j) & 0x01){ATT_Din=1;}
else
{ATT_Din=0;}
ATT_SCLK=0; //送时钟
}
delay_us(30) ;
1、SPI 总线速度: 波特率可以高达 5Mbps,具体速度大小取决于 SPI 硬件。 例如,Xicor 公司的 SPI 串行器件传输速度能达到 5MHz; ATMEL 的 AT45DB021B,20 MHz Max Clock Frequency;
LPC2214 的 SPI,最大数据位速率为输入时钟速率的 1/8。
for( j=0;j<8;j++)
{
SET7022_SCLK; //送时钟
if((comm<<j)&0x80){SET7022_Din;}
else
{CLR7022_Din;}
nop;
nop;
nop;
CLR7022_SCLK; //送时钟
}
CLR7022_Din;
delay_us(50); //等待
从设备,如
没有 CS 信号,则只能存在一个从设备,主设备通过产生移
位时钟来发起通讯。
在 SPI 传输中,数据是同步进行发送和接收的。数据传输的时钟基于 来自主处理器的时钟脉冲,摩托罗拉没有定义任何通用 SPI 的时钟规范。然而, 最常用的时钟设置基于时钟极性(CPOL)和时钟相位(CPHA)两个参数,CPOL 定 义 SPI 串行时钟的活动状态,而 CPHA 定义相对于 SO-数据位的时钟相位。CPOL 和 CPHA 的设置决定了数据取样的时钟.
for( j=0;j<24;j++) //读数据
{
rbyte=rbyte<<1;
SET7022_SCLK;
rbyte=rbyte|((uchar)(ATT_Dout));
nop;
nop;
nop;
CLR7022_SCLK;
}
SET7022_CS;
//释放 SPI
#asm("sei")
//开中断
return rbyte;
}
}
/************************************************************
*************************/
Write_SPI(uchar comm,ulong DAT)
{
uchar j;
if(ATT_SIG==0)
{
#asm("cli")
====在一次数据传输过程中,接口上只能有一个主机和一个从机能够 通信。并且,主机总是向从机发送一个字节数据,而从机也总是向主机发送一个 字节数据。
该总线通信基于主-从配置。它有 4 个信号:
MOSI:主出/从入
MISO:主入/从出
SCK:串行时钟
SS:从属选择 。即 CS(从使能信号),CS 决定了唯一的与主设备通信的
模拟 SPI 程序.zip > spi.c 1. //"首先定义好 IO 口 2. sbit sck=P1^0; 3. sbit si=P1^1;
4. sbit so=P1^2; 5. 6. //"通用 SPI 串口模拟程序 byte=unsigned char 7. byte spi(byte x) 8. { byte i,j; 9. 10. j=sck=0;so=1; 11. for(i=0;i<8;i++) //"发数据 12. { if(x&0x80)si=1; 13. else si=0; 14. x=x<<1; 15. _nop_(); //"根据芯片速度与单片机时钟调整延时 16. _nop_(); //"适当增加或减少 NOP 指令 17. sck=1; 18. j=j<<1; 19. if(so)j=j|0x01; //"读数据 20. _nop_(); 21. _nop_(); 22. sck=0; 23. } 24. return j; 25. }