免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
嵌入式開(kāi)發(fā)筆記——CPLD與MCU模擬SPI通信
  • 作者:zzssdd2
  • E-mail:zzssdd2@foxmail.com

一、需求描述

  • MCU需要接收來(lái)自CPLD的升級(jí)固件數(shù)據(jù)
  • CPLD對(duì)MCU只進(jìn)行發(fā)送數(shù)據(jù),不接收MCU的數(shù)據(jù)
  • CPLD無(wú)法告知數(shù)據(jù)傳輸?shù)拈_(kāi)始和結(jié)束,需要MCU自行判斷(CPLD只是數(shù)據(jù)透?jìng)?,不做?shù)據(jù)判斷)
  • 數(shù)據(jù)通信速率至少是UART通信的115200波特率
  • PCB上MCU與CPLD之間通過(guò)3個(gè)普通IO引腳連接

二、功能分析

  • MCU與CPLD之間有3根線,那么可以選擇UART通信或者SPI通信方式。

  • 由于CPLD無(wú)法通知MCU數(shù)據(jù)傳輸?shù)拈_(kāi)始與結(jié)束,MCU需要自行判別,那么MCU可以通過(guò)中斷方式來(lái)檢測(cè)數(shù)據(jù)傳輸?shù)拈_(kāi)始,通過(guò)超時(shí)來(lái)檢測(cè)數(shù)據(jù)傳輸?shù)慕Y(jié)束。

  • UART與SPI的區(qū)別在于前者是異步通信后者是同步通信方式,不論是SPI還是UART方式都需要MCU通過(guò)IO模擬方式軟件實(shí)現(xiàn)。使用UART傳輸如果收發(fā)雙方產(chǎn)生的波特率存在偏差則會(huì)導(dǎo)致數(shù)據(jù)傳輸出錯(cuò),而同步傳輸方式有時(shí)鐘信號(hào)的約束,相比異步傳輸方式數(shù)據(jù)準(zhǔn)確率會(huì)更高。如果使用軟件模擬UART,需要使用定時(shí)器作為波特率發(fā)生器。如果波特率比較高,那么定時(shí)器中斷頻率就需要更高,這樣會(huì)影響整個(gè)MCU系統(tǒng)的實(shí)時(shí)性。綜合考慮后選擇SPI方式。

  • CPLD對(duì)MCU只發(fā)送數(shù)據(jù),那么MCU只需要作為SPI的從機(jī)即可,三個(gè)IO分配為SPI的CS、CLK、DAT引腳。

  • 由于CS是低電平有效,那么將CS引腳配置為中斷輸入方式,當(dāng)CS中斷觸發(fā)后開(kāi)始數(shù)據(jù)接收處理。因?yàn)镃PLD也不知道數(shù)據(jù)傳輸什么時(shí)候結(jié)束,所以無(wú)法通過(guò)將CS置高電平來(lái)告訴數(shù)據(jù)傳輸?shù)慕Y(jié)束,那么CS置高電平只能表明一個(gè)字節(jié)傳輸結(jié)束。MCU可以通過(guò)超時(shí)方式來(lái)判斷一包數(shù)據(jù)的結(jié)束,類似于串口的空閑中斷方式。

  • SPI數(shù)據(jù)接收在外部中斷中操作。將CLK引腳配置為外部中斷的上升沿觸發(fā),CS有效的情況下CLK中斷觸發(fā)后進(jìn)行數(shù)據(jù)接收。

  • SPI空閑中斷采用100us周期定時(shí)器判斷。為了MCU系統(tǒng)的實(shí)時(shí)性,只有CS中斷觸發(fā)后才會(huì)開(kāi)啟定時(shí)器,超時(shí)判斷完成后關(guān)閉定時(shí)器。

  • CPLD向MCU發(fā)送一字節(jié)的時(shí)序圖如下(速率:200KBit/s):

三、軟件實(shí)現(xiàn)

GPIO的配置:無(wú)數(shù)據(jù)CLK為低電平,CS低有效。CS上升沿、下降沿都會(huì)觸發(fā)中斷,判斷1字節(jié)傳輸?shù)钠鹗寂c結(jié)束;CLK上升沿觸發(fā)中斷,數(shù)據(jù)在CLK上升沿采樣

/*
***********************************************************************************************
*	函	數(shù): BSP_CPLD_GPIO_Init
*	描	述: 配置CPLD的SPI通信引腳
*	輸	入: 無(wú)
*	輸	出: 無(wú)
***********************************************************************************************
*/
void BSP_CPLD_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    CPLD_PIN_CLK_ENABLE();

    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Pin 	= CPLD_SPI_CSN_PIN;
    GPIO_InitStruct.Mode 	= GPIO_MODE_IT_RISING_FALLING;
    GPIO_InitStruct.Pull 	= GPIO_PULLUP;
    HAL_GPIO_Init(CPLD_SPI_CSN_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin		= CPLD_SPI_SCK_PIN;
    GPIO_InitStruct.Mode	= GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull 	= GPIO_PULLDOWN;
    HAL_GPIO_Init(CPLD_SPI_SCK_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin		= CPLD_SPI_DAT_PIN;
    GPIO_InitStruct.Pull	= GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull 	= GPIO_NOPULL;
    HAL_GPIO_Init(CPLD_SPI_DAT_PORT, &GPIO_InitStruct);
}

CPLD_SPI_CS外部中斷函數(shù):用于使能數(shù)據(jù)接收、空閑檢測(cè)

/*
***********************************************************************************************
*	函	數(shù): CPLD_CS_EXTI_IRQHandler
*	描	述: CPLD_SPI_CS中斷函數(shù)
*	輸	入: 無(wú)
*	輸	出: 無(wú)
***********************************************************************************************
*/
void CPLD_CS_EXTI_IRQHandler(void)
{
    if (__HAL_GPIO_EXTI_GET_IT(CPLD_SPI_CSN_PIN))
    {
        if (READ_BIT(CPLD_SPI_CSN_PORT->IDR, CPLD_SPI_CSN_PIN))
        {
            /* CS高失能SPI數(shù)據(jù)接收 */
            CLEAR_BIT(g_tCpldSpi.ucState, CPLD_FLAG_CSN);
        }
        else
        {
            /* CS低使能SPI數(shù)據(jù)接收 */
            s_tCpldSpi.ucByte = 0;
            s_tCpldSpi.ucBitCount = 0;
            SET_BIT(g_tCpldSpi.ucState, CPLD_FLAG_CSN);

            /* 開(kāi)啟空閑檢測(cè) */
            if (0 == s_tCpldSpi.ucIdleCheck)
            {
                s_tCpldSpi.ucIdleCheck = 1;
                HAL_TIM_Base_Start_IT(&Tim7Handle);
            }
        }
        __HAL_GPIO_EXTI_CLEAR_IT(CPLD_SPI_CSN_PIN);
    }
}

CPLD_SPI_SCK外部中斷函數(shù):用于SPI數(shù)據(jù)的接收

/*
***********************************************************************************************
*	函	數(shù): CPLD_SCK_EXTI_IRQHandler
*	描	述: CPLD_SPI_SCK中斷函數(shù)
*	輸	入: 無(wú)
*	輸	出: 無(wú)
***********************************************************************************************
*/
void CPLD_SCK_EXTI_IRQHandler(void)
{
    if (__HAL_GPIO_EXTI_GET_IT(CPLD_SPI_SCK_PIN))
    {
        /* CSN有效則進(jìn)行數(shù)據(jù)接收 */
        if (READ_BIT(g_tCpldSpi.ucState, CPLD_FLAG_CSN))
        {
            if (READ_BIT(CPLD_SPI_DAT_PORT->IDR, CPLD_SPI_DAT_PIN))
            {
                s_tCpldSpi.ucByte |= (0x80 >> s_tCpldSpi.ucBitCount);
            }
            else
            {
                s_tCpldSpi.ucByte &= ~(0x80 >> s_tCpldSpi.ucBitCount);
            }
            /* 收滿一字節(jié)后存向接收FIFO */	
            if (++s_tCpldSpi.ucBitCount > 7)
            {
                g_tCpldSpi.ucaRxBuf[g_tCpldSpi.usRxWrite] = s_tCpldSpi.ucByte;
                if (++g_tCpldSpi.usRxWrite >= 1024)
                {
                    g_tCpldSpi.usRxWrite = 0;
                }
                if (g_tCpldSpi.usRxCount < CPLD_SPI_RX_BUF_LEN)
                {
                    g_tCpldSpi.usRxCount++;
                }
                /* SPI收到新數(shù)據(jù),設(shè)置一個(gè)標(biāo)記,供應(yīng)用程序查詢 */
                SET_BIT(g_tCpldSpi.ucState, CPLD_FLAG_RXNE);
            }
        }
        __HAL_GPIO_EXTI_CLEAR_IT(CPLD_SPI_SCK_PIN);
    }
}

定時(shí)器中斷函數(shù):判斷CPLD_SPI空閑中斷的發(fā)生

/*
***********************************************************************************************
*	函	數(shù): TIM7_IRQHandler
*	描	述: 定時(shí)器7中斷函數(shù),100us中斷周期
*	輸	入: 無(wú)
*	輸	出: 無(wú)
***********************************************************************************************
*/
void TIM7_IRQHandler(void)
{	
    static uint16_t t100us_cnt = 0;

    if (__HAL_TIM_GET_FLAG(&Tim7Handle, TIM_FLAG_UPDATE) &&
    __HAL_TIM_GET_IT_SOURCE(&Tim7Handle, TIM_IT_UPDATE))
    {
        /* CPLD-SPI空閑檢測(cè),1ms */
        if (READ_BIT(g_tCpldSpi.ucState, CPLD_FLAG_CSN))
        {
            t100us_cnt = 0;
        }
        else
        {
            t100us_cnt++;
        }

        if (t100us_cnt > 10)
        {
            /* SPI收到一幀數(shù)據(jù),設(shè)置一個(gè)標(biāo)記,供應(yīng)用程序查詢 */
            SET_BIT(g_tCpldSpi.ucState, CPLD_FLAG_IDLE);
            #if ENABLE_RTOS
            tx_event_flags_set(&tx_event_flags, TX_EVENT_CPLD_SPI_IDLE, TX_OR);
            #endif
            s_tCpldSpi.ucIdleCheck = 0;
            HAL_TIM_Base_Stop_IT(&Tim7Handle);
        }
        __HAL_TIM_CLEAR_IT(&Tim7Handle, TIM_IT_UPDATE);
    }
}

四、功能驗(yàn)證

經(jīng)多次發(fā)送固件數(shù)據(jù)驗(yàn)證,MCU均能正常接收數(shù)據(jù),并且沒(méi)有出現(xiàn)數(shù)據(jù)錯(cuò)誤的情況,可用于該項(xiàng)目。

五、拓展

該方法也可以用于實(shí)現(xiàn)模擬UART功能,僅提供思路,未經(jīng)過(guò)驗(yàn)證(以115200,8-N-1為例)。

  • 將UART的接收引腳配置為上拉模式、下降沿觸發(fā)中斷(判斷起始位)。
  • 中斷第一次觸發(fā)后表明收到起始位,收到起始位后打開(kāi)定時(shí)器中斷(如果波特率為115200,那么中斷周期應(yīng)小于8.6us,如果每Bit數(shù)據(jù)需要多次采樣,則需要更短的中斷周期)。
  • 每中斷一次判斷一次數(shù)據(jù)引腳,數(shù)據(jù)收滿10Bit后判斷是否為停止位,若數(shù)據(jù)接收正確則存入接收FIFO。
  • 在收到起始位后開(kāi)始計(jì)時(shí),1ms內(nèi)沒(méi)有再次收到起始位則認(rèn)為收到一幀數(shù)據(jù),產(chǎn)生軟空閑中斷,然后關(guān)閉定時(shí)器。

使用該UART方式優(yōu)勢(shì)在于比SPI方式使用更少的引腳,只需要1個(gè)IO即可完成通信。缺點(diǎn)在于如果要求通信速率高或需要多次采樣,那么產(chǎn)生波特率的定時(shí)器中斷頻率高,如果被其他更高優(yōu)先級(jí)中斷打斷可能造成波特率不準(zhǔn),數(shù)據(jù)錯(cuò)誤。還有就是UART方式在數(shù)據(jù)通信速率上沒(méi)有SPI有優(yōu)勢(shì)。不到萬(wàn)不得已不建議使用軟件UART方式。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
LCD的CPU接口和RGB接口
st7735s SPI驅(qū)動(dòng)顯示圖標(biāo)
如何移植使用W5500官方提供的最新Socket庫(kù)
軟件模擬SPI接口程序代碼(4種模式)
萬(wàn)字長(zhǎng)文解讀STM32-1
STM32|基于 SPI 單向發(fā)送的 12864 驅(qū)動(dòng)程序
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服