C語言spi
① 求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
}
② SPI怎麼發送五個位元組,求C語言程序
void writedata(unsigned char *pt,unsigned int n) //pt為輸入位元組的頭地址,n為輸入位元組的個數
{
unsigned int i=8;
unsigned char temp;
while(n--)
{
while(i--)
{
temp=*pt;
SCLK=0;
if((temp&=0x80))
SDIN=1;
else
SDIN=0;
SCLK=1;
temp<<=1;
}
pt++;
}
③ 大家有沒有SPI的c程序,用51寫的,謝謝!!!
調試已經通過
///////////////////////////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;
}
////////////////////////////////////////////////////////////////
④ C語言中的問題,怎麼在程序中快速更換SPI介面的CS腳
給你提供下思路,供參考。
sbit cs1=P1^0;
//共定義10個片選,這是少不了的。
//或者你增加硬體,使用3-8解碼器,3個管腳就夠了。
void spi_cs(unsigned char x)
{
switch(x)
{
case 1:
cs1=0;
break;
case 2:
cs2=0;
break;
//以此類推
}
}
⑤ c語言中spiwrite(command,0x00)是什麼意思
這不是一個標准函數
一般是SPI通信協議的IC
這個函數理解 對IC晶元寫COMMAND,值為0
⑥ spi是什麼
SPI:高速同步串列口。3~4線介面,收發獨立、可同步進行
API (Application Programming Interface)
所謂API本來是為C和C++程序員寫的。API說來說去,就是一種函數,他們包含在一個附加名為DLL的動態連接庫文件中。用標準的定義來講,API就是Windows的32位應用程序編程介面,是一系列很復雜的函數,消息和結構,它使編程人員可以用不同類型的編程語言編制出的運行在Windows95 和Windows NT操作系統上的應用程序。可以說,如果你曾經學過VC,那麼API對你來說不是什麼問題。但是如果你沒有學過VC,或者你對Windows95的結構體系不熟悉,那麼可以說,學習API將是一件很辛苦的事情。
⑦ C語言#define SPI2 ((SPI_TypeDef *) SPI2_BASE)中後面的如何解釋
SPI2_BASE應該是寄存器的地址,或基地址。
比如
#define SPI2_BASE 0xAAAAAAAA
通過#define SPI2 ((SPI_TypeDef *) SPI2_BASE)後,
可以去利用SP2去讀寫0xAAAAAAAA指向內存。
比如
SP2 = 0x1;
。。。。。。。。。
⑧ SD卡 SPI模式 c語言 怎麼寫
自己網路一下znfat,是講怎麼寫SD卡,怎麼建立FAT系統,有視頻教程的。
http://u.youku.com/user_video/id_UMTQxNDE4ODg=_order_1_type_1_page_2.html
⑨ stm32f103怎麼用c語言初始化spi1
#include "stm32f10x_conf.h"
uint8_t SPI1_Rx_Buf[4096];
uint8_t SPI1_Tx_Buf[4096];
/**
* @brief Configures the SPI1 Peripheral.
* @param None
* @retval None
*/
void SPI1_Config(void){
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Peripheral Clock Enable -------------------------------------------------*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* Enable the SPI1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/* Enable GPIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Forces or releases High Speed APB (APB2) peripheral reset --------------*/
RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
/* SPI GPIO Configuration --------------------------------------------------*/
/*
* PB4 --> SPI1 MISO Mode: GPIO_Mode_IPU
* PB3 --> SPI1 SCK Mode: GPIO_Mode_AF_PP
* PB5 --> SPI1 MOSI Mode: GPIO_Mode_AF_PP
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SPI1,ENABLE);
SPI_Cmd(SPI2, DISABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* DMA1 Channel2 Configures for SPI1 Receive */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_Rx_Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 0;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
/* Enable DMA1 Channel4 SPI2_RX */
DMA_Cmd(DMA1_Channel2, DISABLE);
/* DMA1 Channel3 Configures for SPI1 Send */
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_Tx_Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
/* Enable DMA1 Channel3 SPI2_TX */
DMA_Cmd(DMA1_Channel3, DISABLE);
/* Enable the DMA1_Channel2、DMA1_Channel3 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_Init(&NVIC_InitStructure);
/* Enable SPI1 */
SPI_Cmd(SPI1, ENABLE);
}