1. 程式人生 > >如何從Cortex-m向STM32移植使用SPI介面協議

如何從Cortex-m向STM32移植使用SPI介面協議

/*****************************************************************************************************
 * @brief:LDC1000應用程式
 * ____________________________
 * |PB4(SSI2CLK)---->SCLK|
 * |PB5(SSI2FSS)---->CSB |
 * |PB6(SSI2RX)    <----       SDO|
 *  Tiva M4|PB7(SSI2TX)---->SDI|LDC1000
 * |PA4(INT/GPIO)<----INTB|
 * |PB0(Timer CLK)---->  TBCLK|
 * _____________||______________
 *****************************************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "driverlib/rom.h"
#include "driverlib/adc.h"
#include "driverlib/sysctl.h"
#include "driverlib/pwm.h"
#include "driverlib/timer.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
#include "driverlib/ssi.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_gpio.h"
#include "LDC1000_cmd.h"
#include "inc/hw_timer.h"
#include "inc/hw_types.h"
#include "inc/hw_ssi.h"


#ifndef TARGET_IS_BLIZZARD_RA1
#define TARGET_IS_BLIZZARD_RA1
#endif


#ifndef  PART_TM4C123GH6PM
#define  PART_TM4C123GH6PM
#endif




#define SPI_RWBIT 0x80                           //LDC1000,SPI時序讀寫位,1=讀,0=寫


unsigned long ProximityData;                                           //LDC上Proximity Data
unsigned long FrequencyData;                                           //LDC1000上的Frequency Data
volatile unsigned char DataRdy ;                                       //LDC1000中斷標誌


uint32_t DataRcv[5] ;                                                  //儲存SPI讀取的資料




/********************************************************************
 * @brief:SPI寫資料
 * @param:unsigned int,SPIdata:待寫的資料
 * @return:none
 *********************************************************************/
void SPIDataSend(unsigned int SPIdata)
{
     SSIDataPut(SSI2_BASE,SPIdata); //SPI傳送(寫)資料
while(SSIBusy(SSI2_BASE)) ;           //等待SPI傳送(寫)完成
}


/********************************************************************
 * @brief:LDC1000初始化配置,ps:在SPI中配置了資料位16個數據長度,故
 * 在傳送資料時可以將地址和值進行或運算一起傳送出去
 * @param:none
 * @return:none
 *********************************************************************/
void LDC1000_init()
{


SPIDataSend(LDC1000_CMD_RPMAX<<8|TEST_RPMAX_INIT);//配置Rp_MAX(0x01)暫存器
SPIDataSend(LDC1000_CMD_RPMIN<<8|TEST_RPMIN_INIT);//配置Rp_MIN(0x02)暫存器
SPIDataSend(LDC1000_CMD_SENSORFREQ<<8|0x94);//配置Sensor Frequency(0x03)暫存器
SPIDataSend(LDC1000_CMD_LDCCONFIG<<8|0x17);//配置LDC Configuration(0x04)暫存器
SPIDataSend(LDC1000_CMD_CLKCONFIG<<8|0x00);//配置Clock Configuration(0x05)暫存器,
//使用TBCLK作為時鐘源


SPIDataSend(LDC1000_CMD_INTCONFIG<<8|0x02);//配置INTB Pin Configuration(0x0A),
//配置INTB為比較輸出標誌位(status of Comparator output)


SPIDataSend(LDC1000_CMD_THRESHILSB<<8|0x50);//配置Comparator Threshold High(0x06)暫存器低8位
SPIDataSend(LDC1000_CMD_THRESHIMSB<<8|0x14);//配置Comparator Threshold High(0x07)暫存器高8位
SPIDataSend(LDC1000_CMD_THRESLOLSB<<8|0xC0);//配置Comparator Threshold Low(0x08)暫存器低8位
SPIDataSend(LDC1000_CMD_THRESLOMSB<<8|0x12);//配置Comparator Threshold Low(0x09)暫存器高8位
SPIDataSend(LDC1000_CMD_PWRCONFIG<<8|0x01);//配置Power Configuration(0x0B)暫存器,
//為Active Mode,使能轉化
}




/********************************************************************
 * @brief:使用SPI讀取LDC1000中的資料
 * @param:none
 * @return:none
 *********************************************************************/
void LDCRead()
{


SPIDataSend((LDC1000_CMD_PROXLSB|SPI_RWBIT)<<8);          //寫入將要讀取的Proximity Data LSB暫存器地址(0x21)
SSIDataGet(SSI2_BASE,&DataRcv[0]);                       //讀取上述暫存器中的值,並存入DataRcv[0]
ProximityData|= DataRcv[0] ;


SPIDataSend((LDC1000_CMD_PROXMSB|SPI_RWBIT)<<8);//寫入將要讀取的Proximity Data MSB暫存器地址(0x22)
SSIDataGet(SSI2_BASE,&DataRcv[1]);//讀取上述暫存器中的值,並存入DataRcv[1]
ProximityData|= (DataRcv[1]<<8) ;//組合成ProximityData


SPIDataSend((LDC1000_CMD_FREQCTRLSB|SPI_RWBIT)<<8);//寫入將要讀取的Frequency Counter Data LSB暫存器地址(0x23)
SSIDataGet(SSI2_BASE,&DataRcv[2]);//讀取上述暫存器中的值,並存入DataRcv[2]
FrequencyData|= DataRcv[2] ;


SPIDataSend((LDC1000_CMD_FREQCTRMID|SPI_RWBIT)<<8);//寫入將要讀取的Frequency Counter Data Mid-Byte暫存器地址(0x24)
SSIDataGet(SSI2_BASE,&DataRcv[3]);//讀取上述暫存器中的值,並存入DataRcv[3]
FrequencyData|= (DataRcv[3]<<8) ;


SPIDataSend((LDC1000_CMD_FREQCTRMSB|SPI_RWBIT)<<8);//寫入將要讀取的Frequency Counter Data MSB暫存器地址(0x25)
SSIDataGet(SSI2_BASE,&DataRcv[4]);//讀取上述暫存器中的值,並存入DataRcv[4]
FrequencyData|= (DataRcv[4]<<16) ;//組合成FrequencyData


GPIOIntEnable(GPIO_PORTA_BASE,GPIO_INT_PIN_4);//使能PA4中斷
}


/********************************************************************
 *  @brief:Timer初始化
 *  @param:none
 *  @return:none
 * ____________________________
 * ||
 *  Tiva M4|PB0(Timer CLK)---->  TBCLK|LDC1000
 * _____________||______________
 *********************************************************************/


void TimerInit()
{
TimerDisable(TIMER2_BASE,TIMER_A);
GPIOPinTypeTimer(GPIO_PORTB_BASE,GPIO_PIN_0);
GPIOPinConfigure(GPIO_PB0_T2CCP0);//配置PB0為CCP模式
HWREG(TIMER2_BASE + TIMER_O_CFG) = 0x04;//選擇16-bit timer


//配置TimerA週期計數(Periodic Timer mode)
HWREG(TIMER2_BASE + TIMER_O_TAMR)|=(TIMER_TAMR_TAAMS|TIMER_TAMR_TAMR_PERIOD) ;


//載入Timer計數值:40,並且設定Match值:20(Timer預設為減計數)
HWREG(TIMER2_BASE + TIMER_O_TAMATCHR) = 20;
TimerLoadSet(TIMER2_BASE,TIMER_A,40);


TimerEnable(TIMER2_BASE,TIMER_A);//使能Timer
}


/********************************************************************
 * @brief:PA4初始化
 * @param:none
 * @return:none
 * ____________________
 * ||
 * ||
 * Tiva M4 | PA4  <--- INTB|  LDC1000
 * ||
 * —————————||__________
 *********************************************************************/


void GPIOInit()
{
HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= 1<<4 ;
GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_4,GPIO_RISING_EDGE);     //配置為上升沿中斷
GPIOIntEnable(GPIO_PORTA_BASE,GPIO_INT_PIN_4); //使能PA4中斷
IntEnable(INT_GPIOA); //使能GPIOA中斷
}


/********************************************************************
 *@brief: SPI通訊初始化
 *@param: none
 *@return: none
 * ____________________________
 * |PB4(SSI2CLK)---->SCLK|
 * |PB5(SSI2FSS)---->CSB |
 * |PB6(SSI2RX)    <----       SDO|
 *  Tiva M4|PB7(SSI2TX)---->SDI|LDC1000
 * |PB0(Timer CLK)---->  TBCLK|
 * _____________||______________
 *********************************************************************/


void SPIInit()
{
//配置PB6為SSI2RX,即對Tiva M4而言的SPI資料接收線
GPIOPinTypeSSI(GPIO_PORTB_BASE,GPIO_PIN_6) ;
GPIOPinConfigure(GPIO_PB6_SSI2RX);


//配置PB6為SSI2TX,即對Tiva M4而言的SPI資料傳送線
GPIOPinTypeSSI(GPIO_PORTB_BASE,GPIO_PIN_7) ;
GPIOPinConfigure(GPIO_PB7_SSI2TX);


//配置PB4為SSI2CLK線,作為時鐘線
GPIOPinTypeSSI(GPIO_PORTB_BASE,GPIO_PIN_4) ;
GPIOPinConfigure(GPIO_PB4_SSI2CLK);


//配置PB5為SSI2FFS線,作為片選線
GPIOPinTypeSSI(GPIO_PORTB_BASE,GPIO_PIN_5) ;
GPIOPinConfigure(GPIO_PB5_SSI2FSS);


SSIDisable(SSI2_BASE);                                           //禁能SSI2


//配置SSI2為SSI_FRF_MOTO_MODE_0協議格式,SPI主模式,時鐘源為5K,16位資料長度
SSIConfigSetExpClk(SSI2_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER,5000,16);


SSIEnable(SSI2_BASE) ;//使能SSI2
}


/********************************************************************
 *@brief: PA4中斷服務函式,該函式在startup_ccs.c的中斷向量表中進行
 *了註冊
 *@param: none
 *@return: none
 * ____________________
 * ||
 * ||
 * Tiva M4 | PA4  <--- INTB|  LDC1000
 * ||
 * —————————||__________
 *********************************************************************/
void GPIOAIntHandler()
{
GPIOIntClear(GPIO_PORTA_BASE,GPIO_INT_PIN_4) ;//清除PA4中斷標誌
DataRdy = 1 ; //LDC1000中斷標誌置位
GPIOIntDisable(GPIO_PORTA_BASE,GPIO_INT_PIN_4) ;//禁能PA4中斷,將在SPI資料讀取完成後重新使能PA4中斷
}


//---------------------------------------main函式----------------------------------------------
int main(void)
{

SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |//配置主時鐘為50MHz
                      SYSCTL_OSC_MAIN);


SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA) ;//使能GPIOA外設模組
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB) ; //使能GPIOB外設模組
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); //使能Timer2外設模組
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); //使能SSI2外設模組
    DataRdy = 0 ;//LDC1000中斷標誌清零
    TimerInit() ;//TBCLK所在時鐘初始化
    GPIOInit() ;//GPIO初始化(PA4)
    SPIInit() ;//SPI初始化
    LDC1000_init();//LDC1000初始配置
    ROM_IntMasterEnable();                                         //使能總中斷
    while(HWREG(SSI2_BASE + SSI_O_SR)& SSI_SR_RNE)                 //首先清除SPI上的接收快取,排除干擾
    {
    DataRcv[0] = HWREG(SSI2_BASE + SSI_O_DR) ;
    }
      while(1)
    {


      //轉化結束後讀取ProximityData和FrequencyData
    if(DataRdy)
     {
     DataRdy = 0 ;//LDC1000中斷標誌清零(在PA4中斷服務程式中置位)
     LDCRead() ;//SPI讀取資料操作
      }


    }


}

怎樣在stm32中寫這個程式????

大家一起討論