历史上的今天
返回首页

历史上的今天

今天是:2025年01月16日(星期四)

正在发生

2019年01月16日 | STM32F051 SPI slave mode DMA接收

2019-01-16 来源:eefocus

用STM32F051的SPI从模式接收主机发送的实时数据。


Eclips 环境,gcc编译器,相关源码如下:


#ifdef DEBUG_SPI_EN

#define DEBUG_SPI(...)      printf(__VA_ARGS__)

#else

#define DEBUG_SPI(...)

#endif

 

void SPI1_Config(void)

{

    GPIO_InitTypeDef    GPIO_InitStructure;

    SPI_InitTypeDef     SPI_InitStructure;

 

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

    // SPI1 port

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_5;

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_0);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);

 

    // SPI1 config

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    SPI_I2S_DeInit(SPI1);

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;

    SPI_InitStructure.SPI_Mode      = SPI_Mode_Slave;  

    SPI_InitStructure.SPI_DataSize  = SPI_DataSize_8b; 

    SPI_InitStructure.SPI_CPOL      = SPI_CPOL_High;

    SPI_InitStructure.SPI_CPHA      = SPI_CPHA_1Edge;

    SPI_InitStructure.SPI_NSS       = SPI_NSS_Soft;    

    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;  // SCLK = 12.0MHz

    SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;

    SPI_InitStructure.SPI_CRCPolynomial     = 7;

    SPI_Init(SPI1, &SPI_InitStructure);

 

    SPI_Cmd(SPI1, DISABLE);

}

 

void SPI1_DMA_NVIC_Config(void)

{

    NVIC_InitTypeDef    NVIC_InitStructure;

 

    NVIC_InitStructure.NVIC_IRQChannel         = DMA1_Channel2_3_IRQn;  

    NVIC_InitStructure.NVIC_IRQChannelPriority = 2; 

    NVIC_InitStructure.NVIC_IRQChannelCmd      = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

 

    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);

}

 

void SPI1_DMA_Config(uint8_t *pbuff, uint16_t nbytes)

{

    DMA_InitTypeDef     DMA_InitStructure;

 

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

 

    DMA_DeInit(DMA1_Channel2);

    DMA_StructInit(&DMA_InitStructure);

    DMA_Cmd(DMA1_Channel2, DISABLE);

 

    DMA_InitStructure.DMA_PeripheralBaseAddr= SPI1_BASE + 0x0C;

    DMA_InitStructure.DMA_MemoryBaseAddr    = (uint32_t)pbuff;

    DMA_InitStructure.DMA_BufferSize        = nbytes;

    DMA_InitStructure.DMA_DIR               = DMA_DIR_PeripheralSRC;        // from SPI

    DMA_InitStructure.DMA_PeripheralInc     = DMA_PeripheralInc_Disable;

    DMA_InitStructure.DMA_MemoryInc         = DMA_MemoryInc_Enable;

    DMA_InitStructure.DMA_PeripheralDataSize= DMA_PeripheralDataSize_Byte;

    DMA_InitStructure.DMA_MemoryDataSize    = DMA_MemoryDataSize_Byte;

    DMA_InitStructure.DMA_Mode              = DMA_Mode_Normal;

    DMA_InitStructure.DMA_Priority          = DMA_Priority_High;

    DMA_InitStructure.DMA_M2M               = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel2, &DMA_InitStructure);

 

    SPI1_DMA_NVIC_Config();

}

 

void SPI1_Read_Starting(uint8_t *pbuff, uint16_t nbytes)

{

    DMA_Cmd(DMA1_Channel2, DISABLE);

    DMA1_Channel2->CNDTR = nbytes;

    DMA1_Channel2->CPAR  = SPI1_BASE + 0x0C;

    DMA1_Channel2->CMAR  = (uint32_t)pbuff;

    DMA_Cmd(DMA1_Channel2, ENABLE);

 

    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

    SPI_Cmd(SPI1, ENABLE);

}

 

void SPI1_Read_Stop(void)

{

    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, DISABLE);

    SPI_Cmd(SPI1, DISABLE);

}

 

/*

 *  SPI1_RX & SPI1_TX DMA Interrupt

 */

void DMA1_Channel2_3_IRQHandler(void)

{

    if(DMA_GetFlagStatus(DMA1_FLAG_TC2) != RESET)

    {

        DEBUG_SPI(">>");

        ; // 接收数据处理,略去...

        ;

 

        DMA_ClearITPendingBit(DMA1_FLAG_TC2);

    }

/*

    if(DMA_GetFlagStatus(DMA1_FLAG_TC3) != RESET)

    {

        DMA_ClearITPendingBit(DMA1_FLAG_TC3);

    }*/

}

 

/*

 *  片选中断设置

 */

void SPI1_NSS_Config(void)

{

    EXTI_InitTypeDef   EXTI_InitStructure;

    NVIC_InitTypeDef   NVIC_InitStructure;

 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

 

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource15);

 

    EXTI_InitStructure.EXTI_Line    = EXTI_Line15;

    EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;

    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;  // _Rising  _Falling  _Rising_Falling

    EXTI_InitStructure.EXTI_LineCmd = ENABLE;

    EXTI_Init(&EXTI_InitStructure);

 

    NVIC_InitStructure.NVIC_IRQChannel         = EXTI4_15_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPriority = 0; // Low Medium Hight VeryHigh: 0 - 3

    NVIC_InitStructure.NVIC_IRQChannelCmd      = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

 

    EXTI_ClearITPendingBit(EXTI_Line15);

}

 

void EXTI4_15_IRQHandler(void)

{

    if(EXTI_GetITStatus(EXTI_Line15) != RESET)

    {

        EXTI_ClearITPendingBit(EXTI_Line15);

 

        GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15);

        if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == RESET)

        {

            SPI1_Read_Starting(&dmaBuffPoll[0], FRAME_BYTES);   // startup SPI1 Data receive-only

        }

    }

}

 

起初,SPI设成“1-line bidirectional data mode selected”模式,接收到的数据全为“0”,找了很久的原因,无果;


改为“Receive-only mode”后,一切正常!


推荐阅读

史海拾趣

洲光源(Chau Light)公司的发展小趣事

在洲光源公司的发展历程中,品质一直是其核心竞争力之一。公司始终坚持严格的质量控制标准,从原材料采购到产品生产、检测的每一个环节都严格把关。同时,洲光源还注重品牌塑造和市场推广,通过参加各种行业展会、举办技术交流会等方式,不断提升品牌知名度和影响力。这些努力使得洲光源的红外LED产品逐渐在市场上脱颖而出,成为众多客户的首选品牌。

Harwin公司的发展小趣事

Harbour Industries成立于1965年,起初主要专注于电缆的生产与销售。在20世纪60年代末和70年代初期,随着全球航空航天市场的迅速增长,Harbour敏锐地捕捉到了这一机遇。为了服务这一市场,公司进行了大规模的工厂扩建,并引入了先进的生产设备和技术。这一举措不仅提升了公司的产能,还确保了产品质量能够满足航空领域的高标准。通过不懈努力,Harbour逐渐在航空电缆市场中占据了一席之地。

CONEC公司的发展小趣事

随着技术的不断进步和市场需求的不断变化,CONEC始终坚持产品创新。1985年,D-SUB滤波连接器的推出,是公司技术实力和市场洞察力的体现。这一创新产品不仅满足了当时市场对高性能连接器的需求,也为公司在电子行业中树立了良好的口碑。此后,CONEC不断推出新产品,逐步扩大市场份额,成为全球电子行业的重要参与者。

Eagle Plastic Devices公司的发展小趣事

随着技术创新的不断推进,Eagle Plastic Devices公司开始积极拓展国内外市场。公司通过参加国际电子展会、与知名电子制造商建立战略合作关系等方式,不断提高品牌知名度和市场份额。同时,公司还注重产品质量的提升和售后服务的完善,赢得了客户的信任和好评。在短短几年内,Eagle Plastic Devices公司便成为了电子行业内知名的塑料电子部件供应商。

博巨兴公司的发展小趣事

2005年,博巨兴公司的业绩取得了突破性进展,全年业绩突破5000万元。这一年,公司还与世平科技有限公司展开了战略合作,共同推动芯片行业的发展。此外,公司还成功取得了台湾义隆公司在华东地区的代理权,进一步拓展了市场份额。

Display Elektronik GmbH公司的发展小趣事

随着环保意识的日益增强,Display Elektronik GmbH将绿色环保理念融入到了公司的发展中。公司采用环保材料和生产工艺,减少了对环境的污染。同时,Display Elektronik GmbH还积极推广绿色显示技术,为客户提供更加环保、节能的显示解决方案。这种对环保的关注和投入,让Display Elektronik GmbH在行业中树立了良好的形象。

问答坊 | AI 解惑

我们已经开发了PXA310的开发板,还有必要开发三星的6410吗?

随着智能手机和PDA的使用越来越广泛,各大厂家都纷纷推出芯片方案。其中最为脱出还是以Samsung 和Marvell 两家公司。 Marvell自从收购了Intel 的的通信和应用处理器Xscale业务后,非常关注这块业务,并且于2007年12月份发布其新一代的应用处理器— ...…

查看全部问答>

我有5个由中断直接连接的按键,请问如何识别是哪个管脚产生的中断啊?

其中两个键触发的沿是上升沿和下降沿交替触发的,三个按键是下降沿触发的,我把它们放在一个中断服务程序中了,由于其中一个制约其他的发出消息,现在我不知道如何识别是哪个管脚产生的这个沿导致产生的中断,请教各位了。…

查看全部问答>

如何才能支持fopen等I/O操作

请问大侠s:     一个编译器中如何才能支持fopen等I/O操作呢?是不是C库中必须要包含相关的C库,我现在使用MDK的IDE,它内部有个自己的文件系统,但是我在SDRAM中调试运行的时候,发现运行fopen函数后,程序就跑飞了。我怀疑是fopen库函 ...…

查看全部问答>

大功率LED封装工艺及方案的介绍及讨论

各大LED生产商在上游磊晶技术上不断改进,如利用不同的电极设计控制电流密度,利用ITO薄膜技术令通过LED的电流能平均分布等,使在结构上都尽可能产生最多的。再运用各种不同方法去抽出LED发出的每一粒光子,如生产不同外形的芯片;利用芯片周边有效 ...…

查看全部问答>

RTC用内部的LSI,不知道精度怎么样?

                                 一天下来,能偏差多少秒?正在考虑用内部还是用外部的,麻烦用的朋友说一下,多谢!!!…

查看全部问答>

关于FPGA的倍频

据说FPGA可以倍频,我的板子上是EP2CQ8Q208的芯片,50M的外部晶振,请问最大能倍频到多少啊。提前谢过啦…

查看全部问答>

430产生spwm波形问题

用430 产生一个spwm,我用的是规则采样,当载波比设置为129的时候波形正常,一旦超过129就会失真,如果设置成500那正弦波直接变为尖峰。不知道为什么,请教各位大神啊!!!!!!! 下面是我的程序: void Init(){ MyClkInit(); Chang ...…

查看全部问答>

易电源设计心得体会2

易电源试用心得2         对于易电源模块LMZ10504TZ的带载能力非常出色。它的输入是2.95-5.5V,输出是2.5V.因此可以看出该模块的输入电压范围很大,输出电压稳定。从电力电子知识看可以知道这是一种BUCK电路,即降压 ...…

查看全部问答>

怎样能够检查一个开关电源系统的稳定性

在这里需要求助各位哥哥姐姐,怎样能够检查一个开关电源系统的稳定性?…

查看全部问答>