USART配置成SPI实例代码

在工作中第一次遇到可以将串口当做SPI使用的情况,下面是我在ATSAM4SD16B芯片中书写的将USART配置成SPI使用的代码。

// Include files
#include "component_usart.h"
#include "sam4sd16b.h"
#include "assert.h"
#include "sam_gpio.h"
#include "sysclk.h"

#define USART_SPI                 USART1
#define CONFIG_USART_SPI_DUMMY    0xFF

// Define USART SPI port
#define SPI_NSS_IDX       PIO_PA24_IDX
#define SPI_NSS_FLAGS     (PIO_PERIPH_A | PIO_DEFAULT)

#define SPI_SPCK_IDX      PIO_PA23_IDX
#define SPI_SPCK_FLAGS    (PIO_PERIPH_A | PIO_DEFAULT)

#define SPI_MOSI_IDX      PIO_PA22_IDX
#define SPI_MOSI_FLAGS    (PIO_PERIPH_A | PIO_DEFAULT)

#define SPI_MISO_IDX      PIO_PA21_IDX
#define SPI_MISO_FLAGS    (PIO_PERIPH_A | PIO_DEFAULT)


typedef enum UsartSpiMode
{
    USART_SPI_MODE_0,
    USART_SPI_MODE_1,
    USART_SPI_MODE_2,
    USART_SPI_MODE_3,
}UsartSpiMode_t;

// Functions prototype
void v_usartSpiEnable(void);
void v_usartSpiDisable(void);
void v_usartSpiGPIOConfigure(void);
void v_usartSpiInit(void);
void v_usartSpiWriteByte(uint8_t uc_Data);
void v_usartSpiReadByte(uint32_t* puc_Data);
void v_usartSpiWrite(uint8_t* puc_Data, uint32_t ui_DataLength);
void v_usartSpiRead(uint8_t* puc_Data, uint32_t ui_DataLength);

/*
* Brief: Configure USART SPI pins
* Input: None
* Output: None
* Return: None
*/
void v_usartSpiGPIOConfigure(void)
{
    // Configure IO port
    gpio_configure_pin(SPI_NSS_IDX, SPI_NSS_FLAGS);
    gpio_configure_pin(SPI_SPCK_IDX, SPI_SPCK_FLAGS);
    gpio_configure_pin(SPI_MOSI_IDX, SPI_MOSI_FLAGS);
    gpio_configure_pin(SPI_MISO_IDX, SPI_MISO_FLAGS);

    // Enable peripheral clock
    PMC->PMC_PCER0 = 1 <<ID_USART1; 
}

/*
Brief: Enable USART SPI
Input: None
Output: None
Return: None
*/
void v_usartSpiEnable(void)
{
    USART_SPI->US_CR = US_CR_RXEN;
    USART_SPI->US_CR = US_CR_TXEN;
}

/*
Brief: Disable USART SPI
Input: None
Output: None
Return: None
*/
void v_usartSpiDisable(void)
{
    USART_SPI->US_CR = US_CR_TXDIS;
    USART_SPI->US_CR = US_CR_RXDIS;
}

/*
*Brief: Synchronous mode enable
*Input: None
*Output: None
*Return: None
*/
void v_usartSpiSynchronousModeEnable(void)
{
    USART_SPI->US_MR |= US_MR_SYNC;
}

/*
*Brief: Asynchronous mode enable
*Input: None
*Output: None
*Return: None
*/
void v_usartSpiAsynchronousModeEnable(void)
{
    USART_SPI->US_MR &= ~US_MR_SYNC;
}

/*
*Brief: Set SPI transmit mode
*Input: t_UsartSpiMode, USART SPI transmit mode
*Output: None
*Return: None
*/
void v_usartSpiTransmitMode(UsartSpiMode_t t_SpiMode)
{
    switch(t_SpiMode)
    {
        case USART_SPI_MODE_0:
            USART_SPI->US_MR &= ~US_MR_CPHA;
            USART_SPI->US_MR &= ~US_MR_CPOL;
            break;

        case USART_SPI_MODE_1:
            USART_SPI->US_MR &= ~US_MR_CPHA;
            USART_SPI->US_MR |= US_MR_CPOL;
            break;

        case USART_SPI_MODE_2:
            USART_SPI->US_MR |= US_MR_CPHA;
            USART_SPI->US_MR &= ~US_MR_CPOL;
            break;

        case USART_SPI_MODE_3:
            USART_SPI->US_MR |= US_MR_CPHA;
            USART_SPI->US_MR |= US_MR_CPOL;
            break;
    }
}

/*
* Brief: Reset USART and disable TX and RX
* Input: None
* Output: None
* Return: None
*/
void v_usartSpiReset(void)
{
    /* Disable write protect of USART registers. */
    USART_SPI->US_WPMR = US_WPMR_WPKEY_PASSWD;

    /* Reset registers that could cause unpredictable behavior after reset. */
    USART_SPI->US_MR = 0;
    USART_SPI->US_RTOR = 0;
    USART_SPI->US_TTGR = 0;

    /* Reset transmitter */
    USART_SPI->US_CR = US_CR_RSTTX | US_CR_TXDIS;

    /* Reset Receiver */
    USART_SPI->US_CR = US_CR_RSTRX | US_CR_RXDIS;

    /* Reset status bits (PARE, OVER, MANERR, UNRE and PXBRK in US_CSR). */
    USART_SPI->US_CR = US_CR_RSTSTA;

    /* Drive the pin RTS to 1. */
    USART_SPI->US_CR = US_CR_RTSDIS;

    /* Drive the pin DTR to 1. */
    USART_SPI->US_CR = US_CR_DTRDIS;

}

/*
* Brief: Configure USART1 as SPI mode
* Input: None
* Output: None
* Return: None
*/
void v_usartSpiInit(void)
{
    /* Configure GPIO port */ 
    v_usartSpiGPIOConfigure();

    /* Reset USART */
    v_usartSpiReset();

    /* Set SPI master mode and channel mode. */
    USART_SPI->US_MR |= US_MR_USART_MODE_SPI_MASTER;

    /* Peripheral clock divided(DIV=8) is selected */
    USART_SPI->US_MR |= US_MR_USCLKS_DIV;

    /* Set transmit character length */
    USART_SPI->US_MR |= US_MR_CHRL_8_BIT;

    /* Set SPI transmit mode */
    v_usartSpiTransmitMode(USART_SPI_MODE_0);

    /* The USART drives the SCK pin if USCLKS does not select the external clock SCK */
    USART_SPI->US_MR |= US_MR_CLKO;

    /* Set synchronous mode */
    v_usartSpiSynchronousModeEnable();

    /* Set clock frequency */
    uint32_t ui_ClockFrequency = sysclk_get_cpu_hz(); // 1 2000 0000
    ui_ClockFrequency /= 6;

    /* Set baudrate */
    uint32_t ui_BaudRate = 115200;

    /* Calculate the clock divider according to the formula in SPI mode. */
    uint32_t ui_ClockDivider = (ui_ClockFrequency + ui_BaudRate / 2) / ui_BaudRate; /* 174 */

    /* Generator baudrate */
    USART_SPI->US_BRGR = ui_ClockDivider << US_BRGR_CD_Pos;

    /* Enable SPI */
    v_usartSpiEnable();
}

/*
Brief: Write one byte to USART SPI
Input: uc_Data, need to write data
Output: None
Return: None
*/
void v_usartSpiWriteByte(uint8_t uc_Data)
{
    /* Check if transmit is ready */
    while (!(USART_SPI->US_CSR & US_CSR_TXRDY));

    USART_SPI->US_THR = US_THR_TXCHR(uc_Data);
}

/*
Brief: Read one byte from USART SPI
Input: None
Output: puc_Data
Return: None
*/
void v_usartSpiReadByte(uint32_t* pui_Data)
{
    /* Dummy write one data to slave in order to read data. */
    while (!(USART_SPI->US_CSR & US_CSR_TXRDY));

    USART_SPI->US_THR = US_THR_TXCHR(CONFIG_USART_SPI_DUMMY);

    /* Wait until it's not empty or timeout has reached. */
    while (!(USART_SPI->US_CSR & US_CSR_RXRDY));

    /* Read character */
    *pui_Data = USART_SPI->US_RHR & US_RHR_RXCHR_Msk;
}

/*
Brief: Write data to USART SPI
Input: 1) puc_Data, write data 
       2) ui_DataLength, write data length
Output: None
Return: None
*/
void v_usartSpiWrite(uint8_t* puc_Data, uint32_t ui_DataLength)
{
    uint32_t ui_Index = 0;
    uint32_t ui_DummyData = 0;

    assert(puc_Data != NULL);
    assert(ui_DataLength > 0);

    /* Drive the slave select line NSS (RTS pin) to 0 */
    USART_SPI->US_CR = US_CR_FCS;

    for(ui_Index = 0; ui_Index < ui_DataLength; ui_Index++)
    {
        v_usartSpiWriteByte(puc_Data[ui_Index]);

        /* Wait until it's not empty or timeout has reached. */
        while (!(USART_SPI->US_CSR & US_CSR_RXRDY));

        /* Read character */
        ui_DummyData = USART_SPI->US_RHR & US_RHR_RXCHR_Msk;
    }

    /* Drive the slave select line NSS (RTS pin) to 1 */
    USART_SPI->US_CR = US_CR_RCS;
}

/*
Brief: Read data from USART SPI
Input: ui_DataLength, read data length
Output: puc_Data, read data 
Return: None
*/
void v_usartSpiRead(uint8_t* puc_Data, uint32_t ui_DataLength)
{
    uint32_t ui_Index = 0;
    uint32_t ui_TempData = 0;

    assert(ui_DataLength > 0);

    /* Drive the slave select line NSS (RTS pin) to 0 */
    USART_SPI->US_CR = US_CR_FCS;

    for(ui_Index = 0; ui_Index < ui_DataLength; ui_Index++)
    {
        v_usartSpiReadByte(&ui_TempData);
        puc_Data[ui_Index] = (uint8_t)(ui_TempData & 0xFF);
        ui_TempData = 0;
    }

    /* Drive the slave select line NSS (RTS pin) to 1 */
    USART_SPI->US_CR = US_CR_RCS;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是将MSP430F149的USART配置SPI的示例代码: ```c #include <msp430.h> void USCI_A0_SPI_Init(void) { UCA0CTLW0 |= UCSWRST; // 复位 USCI_A0 控制寄存器 UCA0CTLW0 |= UCSYNC | UCMSB | UCMST | UCCKPH; // 配置SPI 主机模式,使用 3 线 SPI 接口,时钟极性为 1 UCA0CTLW0 |= UCSSEL__SMCLK; // 配置时钟源为 SMCLK UCA0BR0 = 0x02; // 设置时钟分频,时钟频率为 SMCLK / 2 UCA0BR1 = 0x00; UCA0MCTLW = 0x00; // 禁用自动波特率控制 P1SEL0 |= BIT5 | BIT6 | BIT7; // 配置 P1.5、P1.6、P1.7 为 UCA0CLK、UCA0SIMO、UCA0SOMI P1SEL1 &= ~(BIT5 | BIT6 | BIT7); UCA0CTLW0 &= ~UCSWRST; // 启用 USCI_A0 控制器 } void USCI_A0_SPI_WriteByte(uint8_t data) { while (!(UCA0IFG & UCTXIFG)); // 等待发送缓冲区为空 UCA0TXBUF = data; // 将数据写入发送缓冲区 while (!(UCA0IFG & UCRXIFG)); // 等待接收缓冲区有数据 UCA0RXBUF; // 读取接收缓冲区的数据 } uint8_t USCI_A0_SPI_ReadByte(void) { while (!(UCA0IFG & UCTXIFG)); // 等待发送缓冲区为空 UCA0TXBUF = 0xFF; // 发送空字节,接收数据 while (!(UCA0IFG & UCRXIFG)); // 等待接收缓冲区有数据 return UCA0RXBUF; // 返回接收到的数据 } int main(void) { WDTCTL = WDTPW | WDTHOLD; // 停用看门狗定时器 USCI_A0_SPI_Init(); // 初始化 USCI_A0 控制器 while (1) { USCI_A0_SPI_WriteByte(0xAA); // 发送数据 0xAA uint8_t data = USCI_A0_SPI_ReadByte(); // 读取接收到的数据 __delay_cycles(1000); // 延时一段时间 } return 0; } ``` 以上代码实现了将 MSP430F149 的 USART 配置SPI 主机模式,并通过 SPI 接口发送和接收数据。您可以根据自己的实际需求进行修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值