欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 1256|回復(fù): 3
收起左側(cè)

STM32F407標(biāo)準(zhǔn)庫(kù),SPI DMA中斷方式收發(fā)數(shù)據(jù),怎么也調(diào)不通,一進(jìn)DMA收發(fā)中斷程序就...

[復(fù)制鏈接]
回帖獎(jiǎng)勵(lì) 100 黑幣 回復(fù)本帖可獲得 10 黑幣獎(jiǎng)勵(lì)! 每人限 5 次
ID:138119 發(fā)表于 2024-8-19 15:07 | 顯示全部樓層 |閱讀模式
STM32F407標(biāo)準(zhǔn)庫(kù),SPI DMA中斷方式收發(fā)數(shù)據(jù),怎么也調(diào)不通,一進(jìn)DMA收發(fā)中斷程序死了~(等待方式?jīng)]有問(wèn)題),下面是代碼,請(qǐng)高手哥哥姐姐幫忙,謝謝!

//STM32F407標(biāo)準(zhǔn)庫(kù),SPI DMA中斷方式收發(fā)數(shù)據(jù),怎么也調(diào)不通,一進(jìn)DMA收發(fā)中斷程序就...

#define SPI1_RX_LEN                        2000
#define SPI1_TX_LEN                        2000

#define SPI1_DR_ADDR        (uint32_t)0x4001300C

unsigned char SPI1_RX_BUFFER[SPI1_RX_LEN]={0};
unsigned char SPI1_TX_BUFFER[SPI1_TX_LEN]={0};

//函數(shù)名:初始化SPI接口
void SPI1_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);                                //使能SPI1時(shí)鐘
       
        GPIO_InitStructure.GPIO_Pin = SPI1_NSS_Pin;                                                        //IO
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                                                //標(biāo)準(zhǔn)功能
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                                                //推挽輸出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                                        //100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                                                //上拉
        GPIO_Init(SPI1_NSS_GPIO_Port, &GPIO_InitStructure);                                        //初始化
        SPI1_NSS_Set();        //NSS高
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;                        //PA5\6\7復(fù)用功能輸出       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                                                        //復(fù)用功能
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                                                        //推挽輸出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                                                //100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                                                        //上拉
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                        //初始化
       
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1);                                        //PB3復(fù)用為 SPI1
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1);                                        //PB4復(fù)用為 SPI1
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);                                        //PB5復(fù)用為 SPI1
        //只針對(duì)SPI口初始化
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);                                                //復(fù)位SPI1
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);                                        //停止復(fù)位SPI1
       
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;                //設(shè)置SPI單向或者雙向的數(shù)據(jù)模式:SPI設(shè)置為雙線雙向全雙工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                                        //設(shè)置SPI工作模式:設(shè)置為主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                                //設(shè)置SPI的數(shù)據(jù)大小:SPI發(fā)送接收8位幀結(jié)構(gòu)
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                                                                //串行同步時(shí)鐘的空閑狀態(tài)為高電平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                                                        //串行同步時(shí)鐘的第二個(gè)跳變沿(上升或下降)數(shù)據(jù)被采樣
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                                                //NSS信號(hào)由硬件(NSS管腳)還是軟件(使用SSI位)管理:內(nèi)部NSS信號(hào)有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //定義波特率預(yù)分頻的值:波特率預(yù)分頻值為2:42M;4:21M;8:10.5M;16:5.25M
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                                //指定數(shù)據(jù)傳輸從MSB位還是LSB位開(kāi)始:數(shù)據(jù)傳輸從MSB位開(kāi)始
        SPI_InitStructure.SPI_CRCPolynomial = 7;                                                                //CRC值計(jì)算的多項(xiàng)式
        SPI_Init(SPI1, &SPI_InitStructure);                                                                          //根據(jù)SPI_InitStruct中指定的參數(shù)初始化外設(shè)SPIx寄存器

        SPI_Cmd(SPI1, ENABLE);                                //使能SPI外設(shè)
        spi1_dma_init(41,41);                                //DMA初始化
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
}

void spi1_dma_init(unsigned short RXSize,unsigned short TXSize)
{
        DMA_InitTypeDef DMA_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        /*DMA2*/
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
        /* DMA RX config */
        DMA_InitStructure.DMA_Channel = DMA_Channel_3;                                                        //DMA  通道
        DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_ADDR;                                 //外設(shè)地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI1_RX_BUFFER;                //接收緩沖區(qū)(內(nèi)存中的有一個(gè)數(shù)組)
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                                        //DMA 傳輸方向
        DMA_InitStructure.DMA_BufferSize = RXSize;                                                                //DMA 傳輸?shù)臄?shù)量        這個(gè)后期還可以再改
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外設(shè)地址自增  取消
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        //內(nèi)存地址自增  使能
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //傳輸?shù)?單位 (byte  8bit)
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //傳輸?shù)?單位 (byte  8bit)
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        //普通模式  傳輸完成一次就自動(dòng)結(jié)束
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                        //優(yōu)先級(jí) 中等
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                                        //不使用 FIFO
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;                        //
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                //
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream2, &DMA_InitStructure);                                                                //初始化
        /* DMA TX Config */
        DMA_InitStructure.DMA_Channel = DMA_Channel_3;                                                        //DMA  通道
        DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_ADDR;                                //外設(shè)地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI1_TX_BUFFER;                //接收緩沖區(qū)(內(nèi)存中的有一個(gè)數(shù)組)
        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                        //DMA傳輸方向
        DMA_InitStructure.DMA_BufferSize = TXSize;                                                                //DMA傳輸?shù)臄?shù)量        這個(gè)后期還可以再改
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外設(shè)地址自增  取消
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        //內(nèi)存地址自增  使能
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //傳輸?shù)?單位 (byte  8bit)
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //傳輸?shù)?單位 (byte  8bit)
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        //普通模式  傳輸完成一次就自動(dòng)結(jié)束
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                        //優(yōu)先級(jí) 中等
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream3, &DMA_InitStructure);                                                                //初始化
       
        //DMA中斷方式發(fā)送
        DMA_ITConfig(DMA2_Stream3, DMA_IT_TC, ENABLE);                                                        //DMA發(fā)送中斷開(kāi)
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        DMA_ClearITPendingBit(DMA2_Stream3, DMA_IT_TCIF3);
       
        //DMA中斷方式接收       
        DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);                                                        //DMA接收中斷開(kāi)
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);
}

//讀寫數(shù)據(jù)調(diào)用此函數(shù)
void spi1_trans(unsigned char *rx_buf, unsigned char *tx_buf, unsigned short length)       
{
        DMA_Cmd(DMA2_Stream2, DISABLE);                                                                                //關(guān)閉DMA
        DMA_Cmd(DMA2_Stream3, DISABLE);                                                                                //關(guān)閉DMA
       
        DMA_SetCurrDataCounter(DMA2_Stream2, (unsigned short)length);                //設(shè)置DMA的傳輸參數(shù)
        DMA_SetCurrDataCounter(DMA2_Stream3, (unsigned short)length);                //設(shè)置DMA的傳輸參數(shù)

        DMA2_Stream2->M0AR = (uint32_t)rx_buf;                                                                //設(shè)置內(nèi)存的起始地址
        DMA2_Stream3->M0AR = (uint32_t)tx_buf;                                                                //設(shè)置內(nèi)存的起始地址
       
        SPI1->DR;
        //while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);        //等待先前的發(fā)送完畢

        DMA_Cmd(DMA2_Stream2, ENABLE);                                                                                //打開(kāi)DMA開(kāi)始發(fā)送
        DMA_Cmd(DMA2_Stream3, ENABLE);                                                                                //打開(kāi)DMA開(kāi)始接收

        //while( DMA_GetFlagStatus(DMA2_Stream3, DMA_FLAG_TCIF3) == RESET);  //等待數(shù)據(jù)發(fā)送完
        //while( DMA_GetFlagStatus(DMA2_Stream2, DMA_FLAG_TCIF2) == RESET);  //等待
        //DMA_Cmd(DMA2_Stream2, DISABLE);                                                                        //發(fā)送完關(guān)閉DMA
        //DMA_Cmd(DMA2_Stream3, DISABLE);                                                                        //發(fā)送完關(guān)閉DMA
        //DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2);                                                //清楚標(biāo)志位
        //DMA_ClearFlag(DMA2_Stream3, DMA_FLAG_TCIF3);                                                //清楚標(biāo)志位
}

//發(fā)送中斷
void DMA2_Stream2_IRQHandler(void)  
{
        // 清除DMA發(fā)送完成標(biāo)志
        if(DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF2)!= RESET)
    {
                // 清除DMA發(fā)送完成標(biāo)志
                DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);
                DMA_Cmd(DMA2_Stream2, DISABLE);
                u1_printf("S2_TX_IRQ\r\n");
    }
        // 傳輸錯(cuò)誤中斷
        if(DMA_GetITStatus(DMA2_Stream2, DMA_IT_TEIF2) != RESET)
        {
                 DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TEIF2);
                u1_printf("S2_err_TEIF2\r\n");
        }
}       

//接收中斷
void DMA2_Stream3_IRQHandler(void)
{
        // 清除DMA發(fā)送完成標(biāo)志
        if(DMA_GetITStatus(DMA2_Stream3, DMA_IT_TCIF3)!= RESET)
    {
                DMA_ClearITPendingBit(DMA2_Stream3, DMA_IT_TCIF3);
                DMA_Cmd(DMA2_Stream3, DISABLE);
                u1_printf("S3_RX_IRQ\r\n");
    }
       
        // 傳輸錯(cuò)誤中斷
        if(DMA_GetITStatus(DMA2_Stream3, DMA_IT_TEIF3) != RESET)
        {
                 DMA_ClearITPendingBit(DMA2_Stream3, DMA_IT_TEIF3);
                        u1_printf("S3_err_TEIF3\r\n");
        }
}


回復(fù)

使用道具 舉報(bào)

ID:404160 發(fā)表于 2024-8-27 12:12 | 顯示全部樓層
DMA中斷使能:您在spi1_dma_init函數(shù)中使能了DMA中斷,但在spi1_trans函數(shù)中似乎沒(méi)有適當(dāng)?shù)姆绞饺サ却鼶MA中斷發(fā)生。while循環(huán)被注釋掉了,如果DMA中斷沒(méi)有正確觸發(fā),程序就不會(huì)繼續(xù)執(zhí)行。

DMA傳輸方向設(shè)置:在spi1_dma_init函數(shù)中,RX和TX的DMA配置都使用了相同的DMA通道3,這可能會(huì)導(dǎo)致問(wèn)題。通常,接收和發(fā)送應(yīng)該使用不同的DMA通道,以便它們可以同時(shí)進(jìn)行。

中斷服務(wù)函數(shù):在DMA中斷服務(wù)函數(shù)DMA2_Stream2_IRQHandler和DMA2_Stream3_IRQHandler中,您只處理了傳輸完成中斷(TCIF),但是沒(méi)有處理半傳輸完成中斷(HTIF),這可能影響DMA的效率和性能。

SPI傳輸開(kāi)始:在spi1_trans函數(shù)中,您直接啟動(dòng)了DMA,但是沒(méi)有通過(guò)SPI的發(fā)送函數(shù)開(kāi)始傳輸。這可能導(dǎo)致DMA嘗試從SPI讀取/寫入數(shù)據(jù),但是SPI并未開(kāi)始傳輸。

代碼注釋和邏輯:部分代碼被注釋掉,比如等待DMA傳輸完成的循環(huán)。這些代碼如果取消注釋,可能會(huì)幫助程序正常工作

針對(duì)您的代碼,以下是一些具體的檢查點(diǎn):

確保DMA2_Stream2_IRQHandler和DMA2_Stream3_IRQHandler中斷服務(wù)函數(shù)中沒(méi)有無(wú)限循環(huán)。
檢查中斷優(yōu)先級(jí)設(shè)置是否合理,沒(méi)有其他中斷被錯(cuò)誤地屏蔽。
確保ISR中沒(méi)有調(diào)用阻塞函數(shù)或執(zhí)行耗時(shí)操作。
確保DMA中斷標(biāo)志位在ISR中被正確清除。
檢查是否有可能在ISR中訪問(wèn)了被其他任務(wù)使用的共享資源。
回復(fù)

使用道具 舉報(bào)

ID:276685 發(fā)表于 2024-8-27 18:25 | 顯示全部樓層
建議debug一下看程序死在哪,檢查一下void XXXX_IRQHandler(void)這個(gè)函數(shù)在.h文件定義了沒(méi)有,如果沒(méi)有系統(tǒng)會(huì)在中斷來(lái)臨時(shí)進(jìn)入空函數(shù)循環(huán)
回復(fù)

使用道具 舉報(bào)

ID:982617 發(fā)表于 2024-8-29 09:34 | 顯示全部樓層
你的代碼中可能存在以下幾個(gè)問(wèn)題,導(dǎo)致程序進(jìn)入中斷后卡死:  1. **DMA通道配置沖突:** 你在 `spi1_dma_init` 函數(shù)中,對(duì) DMA2 的 Stream2 和 Stream3 都使用了 `DMA_Channel_3`。  STM32F407 的 DMA2 控制器中,Stream2 和 Stream3 共享一個(gè)通道(Channel 3)。 你需要根據(jù) SPI1 的實(shí)際 DMA 請(qǐng)求映射選擇正確的 Stream 和 Channel 組合。 請(qǐng)參考 STM32F407 數(shù)據(jù)手冊(cè)中 "DMA requests mapping" 章節(jié)查找 SPI1_TX 和 SPI1_RX 對(duì)應(yīng)的 DMA 請(qǐng)求。  2. **中斷處理函數(shù)中的 `printf`:**  在中斷處理函數(shù) `DMA2_Stream2_IRQHandler` 和 `DMA2_Stream3_IRQHandler` 中使用了 `u1_printf` 函數(shù)。 在中斷處理函數(shù)中使用 `printf` 等重量級(jí)函數(shù)可能會(huì)導(dǎo)致程序卡死,尤其是在中斷頻繁觸發(fā)的情況下。 盡量簡(jiǎn)化中斷處理函數(shù)的邏輯,例如僅設(shè)置標(biāo)志位或執(zhí)行一些簡(jiǎn)單的操作,將耗時(shí)的操作放到主循環(huán)中處理。  3. **DMA 緩沖區(qū)大小:** 你的 `SPI1_RX_BUFFER` 和 `SPI1_TX_BUFFER` 數(shù)組大小為 2000 字節(jié),請(qǐng)確保你的 MCU 有足夠的 RAM 空間來(lái)容納這兩個(gè)數(shù)組。  4. **DMA 傳輸模式:** 你使用了 `DMA_Mode_Normal` 模式,這意味著每次 DMA 傳輸完成后都需要重新配置 DMA 控制器。 如果你的應(yīng)用需要連續(xù)傳輸數(shù)據(jù),可以考慮使用 `DMA_Mode_Circular` 循環(huán)模式,避免頻繁配置 DMA 控制器。  5. **SPI 配置:** 請(qǐng)確保 SPI1 的波特率、時(shí)鐘極性、時(shí)鐘相位等配置與你的 SPI 從設(shè)備一致。   **建議修改:**  1. **確認(rèn) DMA 通道映射:**  仔細(xì)閱讀 STM32F407 數(shù)據(jù)手冊(cè),確定 SPI1_TX 和 SPI1_RX 對(duì)應(yīng)的 DMA 請(qǐng)求和通道。 修改 `spi1_dma_init` 函數(shù),使用正確的 Stream 和 Channel 初始化 DMA。  2. **簡(jiǎn)化中斷處理:** 將 `u1_printf` 從中斷處理函數(shù)中移除,可以使用全局變量或標(biāo)志位來(lái)指示 DMA 傳輸完成或出現(xiàn)錯(cuò)誤。  3. **檢查內(nèi)存分配:** 確保你的 MCU 有足夠的 RAM 空間來(lái)存儲(chǔ) DMA 緩沖區(qū)。  4. **嘗試循環(huán)模式:** 如果需要連續(xù)傳輸數(shù)據(jù),修改 DMA 模式為 `DMA_Mode_Circular`。  5. **仔細(xì)檢查 SPI 配置:**  確保 SPI1 的配置參數(shù)與你的 SPI 從設(shè)備匹配。   **調(diào)試建議:**  1. 使用調(diào)試器單步執(zhí)行程序,觀察程序卡死的位置。  2. 在中斷處理函數(shù)中設(shè)置斷點(diǎn),查看中斷是否被正確觸發(fā)。  3. 使用邏輯分析儀抓取 SPI 總線上的信號(hào),分析 SPI 通信是否正常。     通過(guò)以上步驟排查問(wèn)題,你應(yīng)該能夠解決 SPI DMA 中斷方式數(shù)據(jù)傳輸?shù)膯?wèn)題。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表