运用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;}}。
STM32之IO口模拟SPI
STM32之IO⼝模拟SPI本⽂介绍如何使⽤STM32标准外设库的GPIO端⼝模拟SPI,本例程使⽤PA5、PA6和PA7模拟⼀路SPI。
SPI有4种⼯作模式,模拟SPI使⽤模式0,即空闲时SCK为低电平,在奇数边沿采样。
本⽂适合对单⽚机及C语⾔有⼀定基础的开发⼈员阅读,MCU使⽤STM32F103VE系列。
1. 简介SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串⾏外围设备接⼝,是⼀种⾼速全双⼯的通信总线。
它被⼴泛地使⽤在要求通讯速率较⾼的场合。
SPI⽤于多设备之间通讯,分为主机Master和从机Slave,主机只有⼀个,从机可以有多个,通过⽚选信号对从机进⾏选择,⼀次只能选择⼀个从机。
通讯只能由主机发起,⽀持的操作分为读取和写⼊,即主机读取从机的数据,以及向从机写⼊数据。
SPI⼀般有4根线,分别是⽚选线SS、时钟线SCK、主设备输出\从设备输⼊MOSI、主设备输⼊\从设备输出MISO,其中除MISO对于主机为输⼊引脚外,其他引脚对于主机均为输出引脚。
因为有独⽴的输⼊和输出引脚,因此SPI⽀持全双⼯⼯作模式,即可以同时接收和发送。
2. 总线传输信号空闲状态:⽚选信号SS低电平有效,那么空闲状态⽚选信号SS为⾼。
开始信号及结束信号:开始信号需要将⽚选信号SS拉低,结束信号需要将⽚选信号SS拉⾼。
通讯模式:SPI有4种通讯模式,分别为0、1、2、3,根据时钟极性和时钟相位确定,时钟极性分别为空闲低电平和空闲⾼电平,时钟相位分别为SCK奇数边沿采样和偶数边沿采样。
常⽤的模式为模式0和模式3。
SPI模式时钟极性(空闲时SCK时钟)时钟相位(采样时刻)0低电平奇数边沿1低电平偶数边沿2⾼电平奇数边沿3⾼电平偶数边沿3. 时序说明以模式0举例说明:空闲状态:⽚选信号SS为⾼,SCK输出低电平。
开始信号:⽚选信号SS变低,SCK输出低电平。
结束信号:⽚选信号SS变⾼,SCK输出低电平。
单片机IO口模拟SPI四种模式的程序
单片机IO口模拟SPI四种模式的程序单片机IO口模拟SPI四种模式的程序#include "iom8535v.h"#define _CPOL 1#define _CPHA 0#define SCK_IO DDRA|=0X01#define MOSI_IO DDRA|=0X02#define MISO_IO DDRA&=0XFB#define SSEL_IO DDRA|=0X08#define SCK_D(X) (X?(PORTA|=0X01):(PORTA&=0XFE)) #define MOSI_D(X) (X?(PORTA|=0X02):(PORTA&=0XFD)) #define SSEL_D(X) (X?(PORTA|=0X08):(PORTA&=0XF7))#define MISO_I() (PINA&0X04)void delay(){unsigned char m,n;for(n=0;n<5;n++);for(m=0;m<100;m++);}/************************************************ 端口方向配置与输出初始化************************************************/ void SPI_Init(void){SCK_IO ;MOSI_IO ;MISO_IO ;SSEL_IO ;SSEL_D(1);MOSI_D(1);#if _CPOL==0SCK_D(0);#elseSCK_D(1);#endif}/**********************************************模式零写数据***********************************************/ #if _CPOL==0&&_CPHA==0 //MODE 0 0 void SPI_Send_Dat(unsigned char dat){unsigned char n;for(n=0;n<8;n++){SCK_D(0);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(1);}SCK_D(0);}/********************************************* 模式零读数据*********************************************/ unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++)SCK_D(0);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(1);}SCK_D(0);return dat;}#endif/********************************************** 模式二写数据***********************************************/ #if _CPOL==1&&_CPHA==0 //MODE 1 0 void SPI_Send_Dat(unsigned char dat){unsigned char n;for(n=0;n<8;n++){SCK_D(1);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(0);}SCK_D(1);}/********************************************* 模式二读数据*********************************************/ unsigned char SPI_Receiver_Dat(void)unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(1);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(0);}SCK_D(1);return dat;}#endif/********************************************* 模式一写数据*********************************************/ #if _CPOL==0&&_CPHA==1 //MODE 0 1 void SPI_Send_Dat(unsigned char dat){unsigned char n;SCK_D(0);for(n=0;n<8;n++){SCK_D(1);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(0);}}/********************************************* 模式一读数据*********************************************/ unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(1);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(0);}SCK_D(0);return dat;}#endif//////////////////////////////////////////////////////////////////////////////////////////////////////////////#if _CPOL==1&&_CPHA==1 //MODE 1 1void SPI_Send_Dat(unsigned char dat){unsigned char n;SCK_D(1);for(n=0;n<8;n++){SCK_D(0);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(1);}}/************************************模式三读数据************************************/unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;SCK_D(0);for(n=0;n<8;n++){ SCK_D(0);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(1);}SCK_D(1);return dat;}#endif/**************************************************************************/ void main() {SPI_Init();DDRB = 0XFF;//#if _CPOL//SCK_D(0);//#endifwhile(1){//SSEL_D(0);//SPI_Send_Dat(0x01);//SPI_Send_Dat(0x31);//SSEL_D(1);SSEL_D(0);SPI_Send_Dat(0x81); PORTB =SPI_Receiver_Dat(); SSEL_D(1);//delay();}}。
51单片机模拟 SPI 总线的方法
51单片机模拟SPI 总线的方法1 引言SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MC U与各种外围设备以串行方式进行通信以交换信息。
外围设置FLASHRAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。
SPI总线系统可直接与各个厂家生产的多种标准外围器件直接接口,该接口一般使用4条线:串行时钟线(SCK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI 和低电平有效的从机选择线SS(有的SPI接口芯片带有中断信号线INT或INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。
由于SPI系统总线一共只需3~4位数据线和控制即可实现与具有SP I总线接口功能的各种I/O器件进行接口,而扩展并行总线则需要8根数据线、8~16位地址线、2~3位控制线,因此,采用SPI总线接口可以简化电路设计,节省很多常规电路中的接口器件和I/O口线,提高设计的可靠性。
由此可见,在MCS51系列等不具有SPI接口的单片机组成的智能仪器和工业测控系统中,当传输速度要求不是太高时,使用SPI总线可以增加应用系统接口器件的种类,提高应用系统的性能。
2 SPI总线的组成利用SPI总线可在软件的控制下构成各种系统。
如1个主MCU和几个从MCU、几个从MCU相互连接构成多主机系统(分布式系统)、1个主MCU和1个或几个从I/O设备所构成的各种系统等。
在大多数应用场合,可使用1个MCU作为控机来控制数据,并向1个或几个从外围器件传送该数据。
从器件只有在主机发命令时才能接收或发送数据。
其数据的传输格式是高位(MSB)在前,低位(LSB)在后。
SPI 总线接口系统的典型结构如图1所示。
当一个主控机通过SPI与几种不同的串行I/O芯片相连时,必须使用每片的允许控制端,这可通过M CU的I/O端口输出线来实现。
但应特别注意这些串行I/O芯片的输入输出特性:首先是输入芯片的串行数据输出是否有三态控制端。
运用4个普通IO口模拟SPI程序等.
#define ATT_CS
PORTB.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) #define CLR7022_SCLK PORTB&=~(1<<4) #define SET7022_CS #define CLR7022_CS PORTB|=(1<<5) PORTB&=~(1<<5)
else MOSI=0; dat<<=1; SCK=1; _nop_(); _nop_(); _nop_(); _nop_(); temp<<=1; if(MISO)temp++; SCK=0; _nop_(); _nop_(); _nop_(); _nop_(); } return temp; }
/************************************************************ *************************/ ulong Read_SPI(uchar comm) { uchar j; ulong rbyte=0; if(ATT_SIG==0) { SET7022_CS; CLR7022_SCLK; CLR7022_CS; #asm("cli") for( j=0;j<8;j++) { //关中断 //使能 SPI
2、SPI 简介: 同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量 用在与 EEPROM、ADC、FLASH 和显示驱动器之类的慢速外设器件通信。 SPI(Serial Peripheral Interface)是一种串行同步通讯协议,由一个主设 备和一个或多个从设备组成, 主设备启动一个与从设备的同步通讯,从而完成数 据的交换。通讯时,数据由 MOSI 输出,MISO 输入,数据在时钟的上升或下 降沿由 MOSI 输出, 在紧接着的下降或上升沿由 MISO 读入, 这样经过 8/16 次 时钟的改变,完成 8/16 位数据的传输。
IO模拟SPI时序
CS=1;
CS=0;
write(0x02); //WRITE
write(add); //首先写入存储数据的地址
write(a); //写入待存储的数据
CS=1;
模块积累:IO模拟SPI时序 2011-05-19 18:21:09| 分类: 嵌入式开发 | 标签: |举报 |字号大
中
小 订阅
SPI是摩托罗拉提出一种比较总线结构,比飞利浦公司提出的IIC总线多出两条线,这两种总线结构都因为占用IO口少而得到了广泛的使用,一般来说,SPI总线与IIC总线都可以用IO模拟,也有相当多的芯片里面集成了IIC与SPI,比如STC12C60S2中就集成了SPI接口。这里就用模拟SPI来进行通信吧!!!!
{
uchar a=0;
ucha
SCK=0; //时钟 低电平
delay(5); //延时一小会
a=a<<1; //a左移一位,腾出最低位
while(++i<250) //防止程序陷入死循环
{
CS=0;
write(0x05); //获取存储器的状态
b=read();
if((b&0x01)==0) //如果读出的最低位为1则表示存储器还在存储,此时单片机等待,知道存储完毕
程序名:
编写人: 李聪
编写时间: 20 年 月 日
硬件支持:
接口说明:
修改日志:
NO.1-
/*********************************************************************************************
四线SPI通信基本知识,以及菊花链模式
四线SPI通信基本知识,以及菊花链模式今天分享的主要内容是来自于ADI公司的SPI知识学习,SPI算是嵌入式开发中最常用的通信方式之一,而大部分嵌入式软件工程师常常更关注于上层软件的开发,容易忘却底层的一些信号格式等,而一旦通信发生点啥问题,往往那是一个措手不及,所以文本作为SPI 接口的重温与巩固是再合适不过了。
串行外设接口(SPI)是微控制器和外围IC(如传感器、ADC、DAC、移位寄存器、SRAM等)之间使用最广泛的接口之一。
本文先简要说明SPI接口,然后介绍ADI公司支持SPI的模拟开关与多路转换器,以及它们如何帮助减少系统电路板设计中的数字GPIO数量。
SPI是一种同步、全双工、主从式接口。
来自主机或从机的数据在时钟上升沿或下降沿同步。
主机和从机可以同时传输数据。
SPI接口可以是3线式或4线式。
本文重点介绍常用的4线SPI接口。
图1.含主机和从机的SPI配置4线SPI器件有四个信号:►时钟(SPICLK,SCLK)►片选(CS)►主机输出、从机输入(MOSI)►主机输入、从机输出(MISO)产生时钟信号的器件称为主机。
主机和从机之间传输的数据与主机产生的时钟同步。
同I2C接口相比,SPI器件支持更高的时钟频率。
用户应查阅产品数据手册以了解SPI接口的时钟频率规格。
SPI接口只能有一个主机,但可以有一个或多个从机。
图1显示了主机和从机之间的SPI连接。
来自主机的片选信号用于选择从机。
这通常是一个低电平有效信号,拉高时从机与SPI总线断开连接。
当使用多个从机时,主机需要为每个从机提供单独的片选信号。
本文中的片选信号始终是低电平有效信号。
MOSI和MISO是数据线。
MOSI将数据从主机发送到从机,MISO 将数据从从机发送到主机。
数据传输要开始SPI通信,主机必须发送时钟信号,并通过使能CS信号选择从机。
片选通常是低电平有效信号。
因此,主机必须在该信号上发送逻辑0以选择从机。
SPI是全双工接口,主机和从机可以分别通过MOSI和MISO线路同时发送数据。
运用4个普通IO口模拟SPI程序等
运用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;}else MOSI=0;dat<<=1;SCK=1;_nop_();_nop_();_nop_();_nop_();temp<<=1;if(MISO)temp++;SCK=0;_nop_();_nop_();_nop_();_nop_();}return temp;}1、SPI总线速度:波特率可以高达5Mbps,具体速度大小取决于SPI硬件。
例如,Xicor公司的SPI串行器件传输速度能达到5MHz;ATMEL的AT45DB021B,20 MHz Max Clock Frequency;LPC2214的SPI,最大数据位速率为输入时钟速率的1/8。
2、SPI简介:同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量用在与EEPROM、ADC、FLASH和显示驱动器之类的慢速外设器件通信。
SPI(Serial Peripheral Interface)是一种串行同步通讯协议,由一个主设备和一个或多个从设备组成,主设备启动一个与从设备的同步通讯,从而完成数据的交换。
通讯时,数据由MOSI 输出,MISO 输入,数据在时钟的上升或下降沿由MOSI 输出,在紧接着的下降或上升沿由MISO 读入,这样经过8/16 次时钟的改变,完成8/16 位数据的传输。
GPIO模拟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的设备中,至少有一个主控设备。
- 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. }