打印
[应用方案]

N76E003-SPI MASTER

[复制链接]
1392|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
磨砂|  楼主 | 2021-8-1 16:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、前言
最近用到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);
}


使用特权

评论回复
沙发
磨砂|  楼主 | 2021-8-1 16:10 | 只看该作者
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
}


使用特权

评论回复
板凳
磨砂|  楼主 | 2021-8-1 16:11 | 只看该作者

逻辑分析波形 (我这里 MOSI 和MISO 选错了 懒得改了)


使用特权

评论回复
地板
磨砂|  楼主 | 2021-8-1 16:11 | 只看该作者
若连续发送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;




使用特权

评论回复
5
磨砂|  楼主 | 2021-8-1 16:12 | 只看该作者
若中断里面直接做连续发送,效果更差

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;
        }





使用特权

评论回复
6
磨砂|  楼主 | 2021-8-1 16:13 | 只看该作者
加上读取
这里就不在中断里面清除了


等读取了数据,再清除

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* 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);
}
//-----------------------------------------------------------------------------------------------------------


使用特权

评论回复
7
磨砂|  楼主 | 2021-8-1 16:14 | 只看该作者
算力有限,8位数据中间27.5us的间隔

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

4157

帖子

2

粉丝