NUC140的SPI库函数还是写的很不错的,我们看这个函数说明:
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvSPI_Open */
/* */
/* Parameters: */
/* eSpiPort [in]: Specify the SPI port */
/* eMode [in]: Specify the operation mode (eDRVSPI_MASTER/eDRVSPI_SLAVE) */
/* eType [in]: Specify the transfer type (eDRVSPI_TYPE0 ~ eDRVSPI_TYPE7) */
/* i32BitLength [in]: Specify the bit length in a transaction (1~32) */
/* */
/* Returns: */
/* E_DRVSPI_ERR_INIT: The specified SPI port has been opened before. */
/* E_DRVSPI_ERR_BUSY: The specified SPI port is in busy status. */
/* E_DRVSPI_ERR_BIT_LENGTH: The specified bit length is out of range. */
/* E_SUCCESS: Success. */
/* */
/* Description: */
/* Configure the operation mode, transfer type and bit length of a transaction of the specified SPI */
/* port. */
/* The timing waveform types: */
/*
DRVSPI_TYPE0:
CS --| Active state |---
_ _ _ _ _ _ _ _
CLK ____| |_| |_| |_| |_| |_| |_| |_| |_____
Tx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |---
Rx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |-----
DRVSPI_TYPE1:
CS --| Active state |---
_ _ _ _ _ _ _ _
CLK ____| |_| |_| |_| |_| |_| |_| |_| |_____
Tx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |-----
Rx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |-----
DRVSPI_TYPE2:
CS --| Active state |---
_ _ _ _ _ _ _ _
CLK ____| |_| |_| |_| |_| |_| |_| |_| |_____
Tx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |---
Rx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |---
DRVSPI_TYPE3:
CS --| Active state |---
_ _ _ _ _ _ _ _
CLK ____| |_| |_| |_| |_| |_| |_| |_| |_____
Tx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |-----
Rx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |---
DRVSPI_TYPE4:
CS --| Active state |---
___ _ _ _ _ _ _ _ ______
CLK |_| |_| |_| |_| |_| |_| |_| |_|
Tx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |------
Rx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |----
DRVSPI_TYPE5:
CS --| Active state |---
___ _ _ _ _ _ _ _ ______
CLK |_| |_| |_| |_| |_| |_| |_| |_|
Tx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |----
Rx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |----
DRVSPI_TYPE6:
CS --| Active state |---
___ _ _ _ _ _ _ _ ______
CLK |_| |_| |_| |_| |_| |_| |_| |_|
Tx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |------
Rx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |------
DRVSPI_TYPE7:
CS --| Active state |---
___ _ _ _ _ _ _ _ ______
CLK |_| |_| |_| |_| |_| |_| |_| |_|
Tx ----| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |----
Rx --| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |----
Master / Slave Transfer Type Matching Table
DRVSPI_TYPE0 <==> DRVSPI_TYPE3
DRVSPI_TYPE1 <==> DRVSPI_TYPE1
DRVSPI_TYPE2 <==> DRVSPI_TYPE2
DRVSPI_TYPE3 <==> DRVSPI_TYPE0
DRVSPI_TYPE4 <==> DRVSPI_TYPE7
DRVSPI_TYPE5 <==> DRVSPI_TYPE5
DRVSPI_TYPE6 <==> DRVSPI_TYPE6
DRVSPI_TYPE7 <==> DRVSPI_TYPE4
*/
/*------------------------------------------------------------------------------------------------------
库函数将不同类型的SPI用图表示的很清楚,只需要去查看芯片的DATASHEET,选择正确的
SPI形式,基本上一次就能调试成功。
SPI是一个四条线的串行通信协议,包括一条时钟线,两条数据线和一条使能线,如果在
一组SPI上复用多个SPI器件,则会有多个使能线。
AD5441是一个SPI控制的DAC,它的数据类型如下:
上升沿发送数据,低电平使能,符合库函数TPYE1,附上程序如下:
/*****************************************
*文件名:SPI_U27_28.c *
*功能:公共变量定义文件 *
******************************************/
#include "SPI_U27_U28.h"
/**************************************************
*函数名: initialize_SPI *
*功能: 初始化SPI *
*出口参数:无 *
*入口参数:无 *
*************************************************/
void initialize_SPI (void)
{
DrvGPIO_InitFunction (E_FUNC_SPI1); //PC.8,PC.9,PC.11设置为SPI
DrvGPIO_InitFunction (E_FUNC_SPI1_SS1); //PB.9设置为SPI
DrvSYS_UnlockProtectedReg (); //解锁受保护的系统寄存器
DrvSYS_SetIPClock (E_SYS_SPI1_CLK, 1); //使能SPI端口1的核心时钟
DrvSYS_LockProtectedReg (); //对系统寄存器上锁
DrvSPI_Open(eDRVSPI_PORT1, //打开SPI端口1
eDRVSPI_MASTER, //设为主控
eDRVSPI_TYPE1, //时钟空闲状态为低电平,在串行时钟下降沿传输数据,上升沿锁存数据
12); //每次传输12比特
DrvSPI_SetClockFreq(eDRVSPI_PORT1, //设定SPI端口1的时钟频率
2000000, //可变时钟1频率为2M
1000000); //可变时钟2频率为1M
//若不选择可变时钟,复位默认时钟源为可变时钟1即DIVIDER的频率,具体可见芯片手册
delay(100); //延迟使时钟稳定
DrvSPI_DisableAutoSS(eDRVSPI_PORT1); //禁止SPI端口1的自动从选择功能
DrvSPI_SetTriggerMode(eDRVSPI_PORT1, eDRVSPI_LEVEL_TRIGGER); //设置从引脚为电平激活模式
DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING); //设置端口1从引脚为低电平激活
DrvSPI_SetEndian (eDRVSPI_PORT1, //设置SPI端口1数据传送为高字节在前
eDRVSPI_MSB_FIRST );
}
/**************************************************
*函数名: SPI_U27_write *
*功能: 调制度写函数 *
*出口参数:无 *
*入口参数:调制度的值,无符号32位(uint型) *
*************************************************/
void SPI_U27_write (uint32_t modulation_value_ )
{
while(DrvSPI_IsBusy(eDRVSPI_PORT1)) //查询SPI端口1是否忙
{
}
DrvSPI_SetSS(eDRVSPI_PORT1, //激活SPI端口1的从引脚1
eDRVSPI_SS1 );
DrvSPI_SingleWrite(eDRVSPI_PORT1, &modulation_value_); //将调制度的值送到SPI发送器中
DrvSPI_SetGo(eDRVSPI_PORT1); //开始发送
DrvSPI_ClrSS(eDRVSPI_PORT1, eDRVSPI_SS1); //使从引脚1非激活
}
/**************************************************
*函数名: monitor_D6 *
*功能: 功率写函数 *
*出口参数:无 *
*入口参数:功率的值,无符号32位(uint型) *
*************************************************/
void SPI_U28_write (uint32_t power_value_)
{
while(DrvSPI_IsBusy(eDRVSPI_PORT1)) //查询SPI端口1是否忙
{
}
DrvSPI_SetSS(eDRVSPI_PORT1, //激活SPI端口1的从引脚0
eDRVSPI_SS0 );
DrvSPI_SingleWrite(eDRVSPI_PORT1, &power_value_); //将功率的值送到SPI发送器中
DrvSPI_SetGo(eDRVSPI_PORT1); //开始发送
DrvSPI_ClrSS(eDRVSPI_PORT1, eDRVSPI_SS0); //使从引脚0非激活
}
头文件为
#ifndef SPI_U27_U28_h
#define SPI_U27_U28_h
#include "common_variables.h"
#include "DrvSPI.h"
#include "delay.h"
#include "DrvGPIO.h"
#include "DrvSYS.h"
extern void initialize_SPI (void); //SPI初始化
extern void SPI_U27_write (uint32_t modulation_value_ ); //芯片U27写入函数,参数为调制度的值
extern void SPI_U28_write (uint32_t power_value_); //芯片U28写入函数,参数为功率值
#endif