導航:首頁 > 操作系統 > 51單片機模擬spi

51單片機模擬spi

發布時間:2022-09-19 20:04:42

『壹』 求51單片機通過I/O口模擬spi實現雙機通信的c語言代碼

#include <reg52.h>
#include <intrins.h>
#define MODE 0 //MODE=1時 為發送代碼 MODE=0時 為接收代碼
typedef unsigned char uchar;
//****************************************IO埠定義***************************************
sbit MISO =P1^2;
sbit MOSI =P1^3;
sbit SCK =P1^1;
sbit CE =P1^0;
sbit CSN =P3^2;
sbit IRQ =P3^3;
//******************************************************************************************
uchar bdata sta; //狀態標志
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT =sta^4;
//*********************************************NRF24L01*************************************
#define TX_ADR_WIDTH 5 // 5 uints TX address width
#define RX_ADR_WIDTH 5 // 5 uints RX address width
#define TX_PLOAD_WIDTH 32 // 32 uints TX payload
#define RX_PLOAD_WIDTH 32 // 32 uints TX payload
uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
uchar code Tx_Buf[TX_PLOAD_WIDTH]={0xff,0xee,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,
0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xee,0xff};//發送數據
uchar Rx_Buf[RX_PLOAD_WIDTH];//接收數據
//***************************************NRF24L01寄存器指令*******************************************************
#define READ_REG 0x00 // 讀寄存器指令
#define WRITE_REG 0x20 // 寫寄存器指令
#define RD_RX_PLOAD 0x61 // 讀取接收數據指令
#define WR_TX_PLOAD 0xA0 // 寫待發數據指令
#define FLUSH_TX 0xE1 // 沖洗發送 FIFO指令
#define FLUSH_RX 0xE2 // 沖洗接收 FIFO指令
#define REUSE_TX_PL 0xE3 // 定義重復裝載數據指令
#define NOP 0xFF // 保留
//*************************************SPI(nRF24L01)寄存器地址****************************************************
#define CONFIG 0x00 // 配置收發狀態,CRC校驗模式以及收發狀態響應方式
#define EN_AA 0x01 // 自動應答功能設置
#define EN_RXADDR 0x02 // 可用信道設置
#define SETUP_AW 0x03 // 收發地址寬度設置
#define SETUP_RETR 0x04 // 自動重發功能設置
#define RF_CH 0x05 // 工作頻率設置
#define RF_SETUP 0x06 // 發射速率、功耗功能設置
#define STATUS 0x07 // 狀態寄存器
#define OBSERVE_TX 0x08 // 發送監測功能
#define CD 0x09 // 地址檢測
#define RX_ADDR_P0 0x0A // 頻道0接收數據地址
#define RX_ADDR_P1 0x0B // 頻道1接收數據地址
#define RX_ADDR_P2 0x0C // 頻道2接收數據地址
#define RX_ADDR_P3 0x0D // 頻道3接收數據地址
#define RX_ADDR_P4 0x0E // 頻道4接收數據地址
#define RX_ADDR_P5 0x0F // 頻道5接收數據地址
#define TX_ADDR 0x10 // 發送地址寄存器
#define RX_PW_P0 0x11 // 接收頻道0接收數據長度(1到32位元組)
#define RX_PW_P1 0x12 // 接收頻道1接收數據長度
#define RX_PW_P2 0x13 // 接收頻道2接收數據長度
#define RX_PW_P3 0x14 // 接收頻道3接收數據長度
#define RX_PW_P4 0x15 // 接收頻道4接收數據長度
#define RX_PW_P5 0x16 // 接收頻道5接收數據長度
#define FIFO_STATUS 0x17 // FIFO棧入棧出狀態寄存器設置
/******************************************延時函數********************************************************/
//長延時
void Delay(unsigned int s)
{
unsigned int i,j;
for(i=0;i<1000;i++)for(j=0;j<s;j++);
}
//短延時
void delay_ms(unsigned int x)
{
unsigned int i,j;
i=0;
for(i=0;i<x;i++)
{
j=108;;
while(j--);
}
}
/************************************IO 口模擬SPI匯流排 代碼************************************************/
uchar SPI_RW(uchar byte)
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++)
{
MOSI=(byte&0x80);

byte=(byte<<1);
SCK=1;
byte|=MISO;
//led=MISO;Delay(150);
SCK=0;
}
return(byte);
}
uchar SPI_RW_Reg (uchar reg,uchar value) // 向寄存器REG寫一個位元組,同時返回狀態位元組
{
uchar status;
CSN=0;
status=SPI_RW(reg);
SPI_RW(value);
CSN=1;
return(status);
}
uchar SPI_Read (uchar reg )
{
uchar reg_val;
CSN=0;
SPI_RW(reg);
reg_val=SPI_RW(0);
CSN=1;
return(reg_val);
}
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)
{
uchar status,byte_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status byte
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
SPI_RW(*pBuf++);
CSN = 1; // Set CSN high again
return(status); // return nRF24L01 status byte
}
#if MODE
/*******************************發*****送*****模*****式*****代*****碼*************************************/
void TX_Mode(void)
{
CE=0;

SPI_RW_Reg(FLUSH_TX,0x00);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1a
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //設置接收數據長度,本次設置為2位元組
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);
CE=1;
delay_ms(100);
}
void Transmit(unsigned char * tx_buf)
{
CE=0; //StandBy I模式
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 裝載接收端地址
SPI_RW_Reg(FLUSH_TX,0x00);
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 裝載數據
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收發完成中斷響應,16位CRC,主發送
CE=1; //置高CE,激發數據發送
delay_ms(150);
}
#else
/*******************************接*****收*****模*****式*****代*****碼*************************************/
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
{
uchar status,uchar_ctr;

CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status uchar

for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)
pBuf[uchar_ctr] = SPI_RW(0); //

CSN = 1;
return(status); // return nRF24L01 status uchar
}
/******************************************************************************************************/
/*函數:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
/*功能:數據讀取後放如rx_buf接收緩沖區中
/******************************************************************************************************/
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
{
unsigned char revale=0;
sta=SPI_Read(STATUS); // 讀取狀態寄存其來判斷數據接收狀況
if(RX_DR) // 判斷是否接收到數據
{
//CE = 0; //SPI使能
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
revale =1; //讀取數據完成標志
//Delay(100);
}
SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到數據後RX_DR,TX_DS,MAX_PT都置高為1,通過寫1來清楚中斷標志
return revale;
}
/****************************************************************************************************/
/*函數:void RX_Mode(void)
/*功能:數據接收配置
/****************************************************************************************************/
void RX_Mode(void)
{
CE=0;

SPI_RW_Reg(FLUSH_RX,0x00);
//SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
//SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1a
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //設置接收數據長度,本次設置為2位元組
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0F);
CE=1;
delay_ms(130);
}
//************************************串口初始化*********************************************************
void StartUART( void )
{ //波特率9600
SCON = 0x50;
TMOD = 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
PCON = 0x00;
TR1 = 1;
}
//************************************通過串口將接收到數據發送給PC端**************************************
void R_S_Byte(uchar R_Byte)
{
SBUF = R_Byte;
while( TI == 0 ); //查詢法
TI = 0;
}
#endif
//************************************主函數************************************************************
void main()
{
int i=0;
CE=0;
SCK=0;
CSN=1;
P1=0x00;
#if MODE //發送 模式代碼
TX_Mode();
//SPI_RW_Reg(FLUSH_RX,0x00);
while(1)
{
Transmit(Tx_Buf);
Delay(10);
sta=SPI_Read(READ_REG + STATUS);
if(TX_DS)
{
P1=sta; //8位LED顯示當前STATUS狀態 發送中斷應使bit5 = 1 燈滅
Delay(100);
SPI_RW_Reg(WRITE_REG + STATUS,sta);
}
if(MAX_RT) //如果是發送超時
{
P1=0x0f; //發送超時時 8位LED燈 bit4 = 1 燈滅
Delay(150);
SPI_RW_Reg(WRITE_REG + STATUS,sta);
}
}
#else //接收 模式代碼
StartUART();
RX_Mode();
Delay(0);//防止編譯警告

while(1)
{
if(nRF24L01_RxPacket(Rx_Buf))
{
for(i=0;i<TX_PLOAD_WIDTH;i++)
R_S_Byte(Rx_Buf[i]);
}
}
#endif
}

『貳』 求51單片機模擬SPI通訊的C程序,最好帶詳解!謝謝

調試已經通過
///////////////////////////spi.h/////////////////////////////
#ifndef
SPI_H
#define
SPI_H
#include
<stc12le5a60s2.h>
#include
<spi.h>
//sfr
P4
=
0xe8;
//STC12LE5A60S2單片機自帶SPI控制器連接
//sbit
VCC1
=
P2^0;//
VCC1
NO
USE
//sbit
SON
=
P1^6
;//
MISO
//sbit
SIN
=
P1^5
;//
MOSI
//sbit
SCKN
=
P1^7
;
//
SCK
sbit
CSN
=
P1^4
;//
28J60
--
CS
//sbit
RSTN
=
P3^5
;
//RST,
no
use
//sbit
INTN
=
P3^3
;
//
INT,
no
use
void
init_spi(void);
void
WriteByte(u8_t
temp);
u8_t
ReadByte(void);
#endif
////////////////////////////////////////////////////////////////
///////////////////////////spi.c/////////////////////////////
#include<spi.h>
//STC12LE5A60S2單片機自帶SPI控制器連接
void
init_spi(void)
{
//SSIG
=
1;
//忽略SS腳
//SPEN
=
1;
//允許SPI工作
//DORD
=
0;
//先傳高位MSB
//MSTR
=
1;
//設置單片機為主機
SPCTL
=
0xD0;
//SPI
Control
Register
SSIG
SPEN
DORD
MSTR
CPOL
CPHA
SPR1
SPR0
0000,0100
SPSTAT
=
0xC0;
//
//IE2
|=
0x02;
//允許SPI中斷控制位
}
void
WriteByte(u8_t
temp)
{
SPDAT
=
temp;
while(!(SPSTAT
&
0x80));
SPSTAT
=
0xC0;
}
u8_t
ReadByte(void)
{
idata
u8_t
temp;
//SPSTAT
=
0xC0;
SPDAT
=
0x00;
while(!(SPSTAT
&
0x80));
temp
=
SPDAT;
SPSTAT
=
0xC0;
return
temp;
}
////////////////////////////////////////////////////////////////

『叄』 51單片機SPI介面是什麼

SPI介面,串列外設介面(Serial Peripheral Interface),一種同步外設介面,它可以便單片機與各種外圍設備以串列方式進行通信以交換信息。外圍設備包括Flash RAM,網路控制器、LCD顯示驅動器、A/D轉換器和MCU等。

一種高速的,全雙工,同步的通信匯流排,並且在晶元的管腳上只佔用四根線,節約了晶元的管腳,同時為PCB的布局上節省空間,提供方便,正是出於這種簡單易用的特性,越來越多的晶元集成了這種通信協議,比如AT91RM9200。




(3)51單片機模擬spi擴展閱讀

利用SPI可以在軟體的控制下構成各種系統。如一個主控制器和幾個從控制器、幾個從控制器相互連接構成多主機系統(分布式系統)、一個主控制器和一個或幾個從I/O設備所構成的各種系統等。

在大多數應用場合,可以使用一個主控制器作為主控機來控制數據,並向一個或幾個從外圍器件傳送該數據。從器件只有在主控機發命令時才能接收或發送數據,其數據的傳輸格式是高位(MSB)在前,低位(LSB)在後。

『肆』 關於用51單片機的IO口模擬SPI驅動NRF2401模塊,

這個是datasheet裡面的介面電路,黃色的埠表示和單片機相連,或者和電源/地相連。除了電源和地信號,其它都是單片機的介面,這些介面就可以在程序中定義成你前面說的樣子

sbitCE= P2^0;

sbit***= P2^5;

sbit***= P2^1;

sbit***=P2^4;

sbit***=P2^2;

sbit***=P2^3

根據實際情況,定義相應的IO口為相應的名字,然後應用就行了

『伍』 求兩個51單片機模擬SPI通信程序,主機和從機的程序!!

1.定義三個gpio: p0-sclk, p1-sdi, p2-sdo;p0用於模擬spi的clock,p1用於接收數據,p2用於f發送數據;硬體上單片機A的p0接單片機B的p0,A的p1接B的p2,A的p2接B的p12.發送程序:clock拉低,sdo輸出0或1(數據),延時一定時間,clock拉高,延時一定時間,這樣A就發送一位數據到B,循環8次就發送一個位元組數據3.接收程序:檢測clock狀態,如果為低,就讀取sdi,直到clock拉高,結束該次輸入,重復8次,讀取一個位元組注意:1。clock空閑狀態為高,發送數據就拉低;2.還需要加入起始停止同步協議,可根據需要進行完善

『陸』 寫一個51單片機模擬SPI匯流排的代碼

這是我復制的,一搜一大堆

#include <reg52.h>
sbit SPI_DI =P0^1; //MMC數據輸入
sbit SPI_DO =P0^0;//MMC數據輸出,可不接
sbit SPI_SCL=P0^2;//時鍾線

void Write_Byte(unsigned char value)
{
unsigned char i;
for (i=0;i<8;i++)
{
if (((value>>(7-i))&0x01)==0x01)
SPI_DI=1;
else SPI_DI=0;
SPI_SCL=0;
delay(5);
//必須要加延時,否則會因為操作太快而不響應。
SPI_SCL=1;
delay(5);
//必須要加延時,否則會因為操作太快而不響應。
}
}

unsigned char Read_Byte()
{
unsigned char temp=0;
unsigned char i;
for (i=0;i<8;i++)
{
SPI_DO=1;
SPI_SCL=0;
delay(5);
temp=(temp<<1)+(unsigned char)SPI_DO;
SPI_SCL=1;
delay(5);
}
return (temp);
}

『柒』 51單片機怎樣實現SPI通訊

用傳統的51單片機實現SPI通訊,需要用I/O腳來模擬SPI協議,這比較麻煩。
選用STC8系列單片機,就具有了SPI介面了
,只需要對寄存器操作就行了。方便了很多了。如下圖,這是STC8系列中的4個子系列,還有其它的子系列,就不再列舉了。

『捌』 關於用51單片機的IO口模擬SPI驅動NRF2401模塊,nrf的CE,CSN和IRQ怎麼與單片機IO口連

I/O口相連,首先要電壓相等,3V不能直接5V。電壓不相等,要在中間串電阻。具體接法,就看你I/O口的定義了。

『玖』 51單片機能利用三線SPI匯流排嗎

可以的,對於沒有SPI介面的51單片機,可以用兩個IO口來模擬SPI時序,也可以用三根線來模擬,三根線時,數據的收發共用一個IO口,即直接將MOSI和MISO短接一起後接單片機的一個普通IO口,有的廠商建議接兩個引腳中間接一個數千歐的電阻後連接在一起

閱讀全文

與51單片機模擬spi相關的資料

熱點內容
android平滑滾動效果 瀏覽:839
什麼是編譯器指令 瀏覽:219
微控制器邏輯命令使用什麼匯流排 瀏覽:885
程序員在學校里是學什麼的 瀏覽:601
oraclejava數據類型 瀏覽:890
程序員考注冊會計師 瀏覽:957
怎麼使用access的命令按鈕 瀏覽:899
有點錢app在哪裡下載 瀏覽:832
博途v15解壓後無法安裝 瀏覽:205
什麼是根伺服器主機 瀏覽:438
安卓手游怎麼申請退款 瀏覽:555
安卓系統如何分享網頁 瀏覽:278
ad如何編譯pcb工程 瀏覽:414
除了滴滴app哪裡還能用滴滴 瀏覽:399
截圖怎麼保存文件夾然後壓縮 瀏覽:8
幻影伺服器怎麼樣 瀏覽:28
具體哪些廣東公司招程序員 瀏覽:870
嵌入式編譯器教程 瀏覽:306
ssl數據加密傳輸 瀏覽:86
51單片機定時器方式2 瀏覽:332