一、前言
最近用到SPI,调试一下N76E003的SPI
首先下最新的BSP,旧的没SPI例程,我现在的是 N76E003_BSP_Keil_C51_V1.0.6
直接撸代码 SPI_Interrupt_Master
二、配置
-
硬件配置
CSS:P15
P10:SCLK
P00:MOSI
P01:MISO -
配置
关闭错误侦测
CSS手动
MSB First
CPOL=0 空闲低电平
CPHA=1 第一个沿(上升)发送数据,第二个沿(下降)采样
时钟 DIV8 =16M/8=2M
三、程序
初始化
void SPI_Initial(void)
{
P15_Quasi_Mode; // P15 (SS) Quasi mode
P10_Quasi_Mode; // P10(SPCLK) Quasi mode
P00_Quasi_Mode; // P00 (MOSI) Quasi mode
P01_Quasi_Mode; // P22 (MISO) Quasi mode
set_DISMODF; // 错误侦测关闭SS General purpose I/O ( No Mode Fault )
clr_SSOE; //CSS自己不自动
clr_LSBFE; // MSB first
clr_CPOL; // The SPI clock is low in idle mode
set_CPHA; // The data is sample on the second edge of SPI clock
set_MSTR; // SPI in Master mode
SPICLK_DIV8; // Select SPI clock
Enable_SPI_Interrupt; // Enable SPI interrupt
set_SPIEN; // Enable SPI function
}
中断,只有发送完成
//-----------------------------------------------------------------------------------------------------------
void SPI_ISR(void) interrupt 9 // Vecotr @ 0x4B
{
clr_SPIF;
spi_send_ok=1;
// Timer3_Delay10us(1);
}
main中循环发送
//-----------------------------------------------------------------------------------------------------------
UINT8 test_data=0;
UINT8 spi_send_ok=1;
void main(void)
{
UINT8 u8MID,u8DID;
Set_All_GPIO_Quasi_Mode;
InitialUART0_Timer1(115200); /* 115200 Baud Rate*/
SPI_Initial();
printf ("\nSPI Start Transmit...\n");
clr_SPIF;
while(1)
{
SS = 0;
spi_send_ok=0;
SPDR = test_data;
while(!spi_send_ok);
SS=1;
test_data+=1;
printf ("\r\n");
P12=!P12;
Timer0_Delay1ms(500);
}
#if 0
Start_Sending_SPI(&u8MID,&u8DID);
if((u8MID != 0x4F)&&(u8DID != 0x4E))
SPI_Error();
printf ("\nSPI Test OK!\n");
while(1) // SPI transmission finish
{
P12 = 1;
Timer0_Delay1ms(500);
P12 = 0;
Timer0_Delay1ms(500);
}
#endif
}
逻辑分析波形 (我这里 MOSI 和MISO 选错了 懒得改了)
若连续发送3个数据 中间有3.8us的延迟
spi_send_ok=0;
SPDR = test_data; // Send 0x90 to Slave
while(!spi_send_ok);
test_data+=1;
spi_send_ok=0;
SPDR = test_data; // Send 0x90 to Slave
while(!spi_send_ok);
test_data+=1;
spi_send_ok=0;
SPDR = test_data; // Send 0x90 to Slave
while(!spi_send_ok);
test_data+=1;
spi_send_ok=0;
SPDR = test_data; // Send 0x90 to Slave
while(!spi_send_ok);
test_data+=1;
若中断里面直接做连续发送,效果更差
void SPI_ISR(void) interrupt 9 // Vecotr @ 0x4B
{
clr_SPIF;
// spi_send_ok=1;
if(test_data<10)
{
SPDR = test_data++;
}
else
{
spi_send_ok=1;
}
// Timer3_Delay10us(1);
}
SS = 0;
spi_send_ok=0;
SPDR = test_data++;
while(1)
{
if(spi_send_ok)SS=1;
}
加上读取
这里就不在中断里面清除了
等读取了数据,再清除
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2017 Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
//***********************************************************************************************************
// Website: http://www.nuvoton.com
// E-Mail : MicroC-8bit@nuvoton.com
// Date : Jan/21/2017
//***********************************************************************************************************
//***********************************************************************************************************
// File Function: N76E003 SPI in Master mode demo code
//***********************************************************************************************************
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
//***********************************************************************************************************
// Application: SPI Function
// Master send 0x90 and recevie 0x4E
// Master send 0x01 and recevie 0x55
// Master send 0x02 and recevie 0x56
// Master send 0x03 and recevie 0x4F
// Master send 0x04 and recevie 0x54
//
// Master recevie 0x4E and 0x4F form slave after transmitting
//
// Output : P1.4 & P2.1 flash when SPI pass
// UART show result on hyper-terminal
// P0.7 flash when SPI error
//***********************************************************************************************************
#if 0
///*****************************************************************************************
//* For ADC INIT setting
//*****************************************************************************************/
//#define SPICLK_DIV2 clr_SPR0;clr_SPR1
//#define SPICLK_DIV4 set_SPR0;clr_SPR1
//#define SPICLK_DIV8 clr_SPR0;set_SPR1
//#define SPICLK_DIV16 set_SPR0;set_SPR1
//#define Enable_SPI_Interrupt set_ESPI;set_EA
//#define SS P15
#endif
UINT8 spi_send_ok=1;
//-----------------------------------------------------------------------------------------------------------
void SPI_Error(void)
{
printf ("\nSPI error.\n");
while(1) // SPI error and P0.7 flash/
{
P07 = 1;
Timer0_Delay1ms(500);
P07 = 0;
Timer0_Delay1ms(500);
}
}
//-----------------------------------------------------------------------------------------------------------
void SPI_Initial(void)
{
P15_Quasi_Mode; // P15 (SS) Quasi mode
P10_Quasi_Mode; // P10(SPCLK) Quasi mode
P00_Quasi_Mode; // P00 (MOSI) Quasi mode
P01_Quasi_Mode; // P22 (MISO) Quasi mode
set_DISMODF; // ½ûÖ¹´íÎóÕì²â SS General purpose I/O ( No Mode Fault )
clr_SSOE; //CSS²»×Ô¶¯ÀµÍ ×Ô¼ºÑ¡Ôñ
clr_LSBFE; // MSB first
clr_CPOL; // The SPI clock is low in idle mode
set_CPHA; // The data is sample on the second edge of SPI clock
set_MSTR; // SPI in Master mode
SPICLK_DIV8; // Select SPI clock
Enable_SPI_Interrupt; // Enable SPI interrupt
set_SPIEN; // Enable SPI function
}
//-----------------------------------------------------------------------------------------------------------
void Start_Sending_SPI(UINT8 *pu8MID,UINT8 *pu8DID)
{
SS = 0;
SPDR = 0x90; // Send 0x90 to Slave
PCON |= SET_BIT0; // Enter idle mode
if(SPDR != 0x4E) // Receive slave 1st DATA
SPI_Error();
printf ("\nSlave Return %c!\n",SPDR);
SPDR = 0x01; // Send 0x01 to Slave
PCON |= SET_BIT0; // Enter idle mode
if(SPDR != 0x55) // Receive slave 2nd DATA
SPI_Error();
printf ("\nSlave Return %c!\n",SPDR);
SPDR = 0x02; // Send 0x02 to Slave
PCON |= SET_BIT0; // Enter idle mode
if(SPDR != 0x56) // Receive slave 3rd DATA
SPI_Error();
printf ("\nSlave Return %c!\n",SPDR);
SPDR = 0x03; // Send 0x03 to Slave
PCON |= SET_BIT0; // Enter idle mode
if(SPDR != 0x4F) // Receive slave 4th DATA
SPI_Error();
printf ("\nSlave Return %c!\n",SPDR);
SPDR = 0x04; // Send 0x04 to Slave
PCON |= SET_BIT0; // Enter idle mode
if(SPDR != 0x54) // Receive slave 5th DATA
SPI_Error();
printf ("\nSlave Return %c!\n",SPDR);
SPDR = 0x4F;
PCON |= SET_BIT0; // Enter idle mode
*pu8MID = SPDR; // Receive Slave 1st DATA fron Slave
printf ("\nSlave Return %c!\n",SPDR);
SPDR = 0x4E;
PCON |= SET_BIT0; // Enter idle mode
*pu8DID = SPDR; // Receive Slave 2nd DATA from Slave
printf ("\nSlave Return %c!\n",SPDR);
SS = 1;
}
void spi_send(uint8_t *tdata,uint8_t *rdata,uint8_t len)
{
uint8_t i;
uint8_t *p;
SS=0;
for(i=0;i<len;i++)
{
spi_send_ok=0;
SPDR = *(tdata+i); //轮训发送数据
while(!spi_send_ok);//等待发送完成
*(rdata+i)=SPDR;//接收数据
clr_SPIF; //接收完了再清标志
//printf ("data[%02x] %02x\r\n",i,rdata);
// Timer3_Delay10us(10);
}
SS=1;
}
//-----------------------------------------------------------------------------------------------------------
uint8_t test_data_s[11]="0123456789";
uint8_t test_data_r[11]="";
void main(void)
{
UINT8 u8MID,u8DID;
Set_All_GPIO_Quasi_Mode;
InitialUART0_Timer1(115200); /* 115200 Baud Rate*/
SPI_Initial();
printf ("\nSPI Start Transmit...\n");
clr_SPIF;
while(1)
{
spi_send(test_data_s,test_data_r,10);
printf ("\r\n");
P12=!P12;
Timer0_Delay1ms(500);
}
#if 0
Start_Sending_SPI(&u8MID,&u8DID);
if((u8MID != 0x4F)&&(u8DID != 0x4E))
SPI_Error();
printf ("\nSPI Test OK!\n");
while(1) // SPI transmission finish
{
P12 = 1;
Timer0_Delay1ms(500);
P12 = 0;
Timer0_Delay1ms(500);
}
#endif
}
//-----------------------------------------------------------------------------------------------------------
void SPI_ISR(void) interrupt 9 // Vecotr @ 0x4B
{
//clr_SPIF;
spi_send_ok=1;
// Timer3_Delay10us(1);
}
//-----------------------------------------------------------------------------------------------------------
算力有限,8位数据中间27.5us的间隔