首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无ASF的SAMD21 SPI配置

无ASF的SAMD21 SPI配置
EN

Stack Overflow用户
提问于 2022-05-16 10:56:52
回答 2查看 158关注 0票数 1

我目前正在进行基于SAMD21J18A C的项目优化工作,我的代码正在工作,但它是基于ASF的,我正试图逐步摆脱它。

我成功地完成了我的大部分代码,但是当我想要配置没有ASF的SPI总线时,我遇到了困难。

我的目标是通过SPI与移位寄存器进行通信以控制LED。

我的ASF代码:

代码语言:javascript
复制
void configure_sercom0_spi(struct spi_module *const spi_master_instance, struct spi_slave_inst *const slave){
    struct spi_config master_config;
    struct spi_slave_inst_config slave_config;
    

    spi_get_config_defaults(&master_config);
    
    master_config.mux_setting = SPI_SIGNAL_MUX_SETTING_E;  // DOPO: 0x1, DIPO: 0x0
    master_config.pinmux_pad0 = PINMUX_PA04D_SERCOM0_PAD0; // MISO PA04
    master_config.pinmux_pad1 = PINMUX_PA05D_SERCOM0_PAD1; // Slave Selection PA05
    master_config.pinmux_pad2 = PINMUX_PA06D_SERCOM0_PAD2; // MOSI PA06
    master_config.pinmux_pad3 = PINMUX_PA07D_SERCOM0_PAD3; // SCK PA07

    master_config.mode_specific.master.baudrate = 0xF4240; // 1000000
    
    spi_slave_inst_get_config_defaults(&slave_config);
    slave_config.ss_pin = PIN_PA05;
    
    spi_init(spi_master_instance, SERCOM0, &master_config);
    spi_attach_slave(slave, &slave_config);
    
    spi_enable(spi_master_instance);
}

我的代码没有ASF (编辑)

代码语言:javascript
复制
#define SPI_LIGHTING_MAIN_CLK_FREQ    0x7A1200  // 8Mhz
#define SPI_LIGHTING_BAUDRATE         0xF4240   // 1000000

// Peripheral function D selected
#define SPI_LIGHTING_PERIPHERAL_MUX_EVEN  0x3
#define SPI_LIGHTING_PERIPHERAL_MUX_ODD   0x3

void gclk_spi_config(void){
    // GCLK generator 0 ; No division
    GCLK->GENDIV.reg            |= GCLK_GENDIV_ID(0)
                                | GCLK_GENDIV_DIV(1);
    
    // Generic generator 0 ; OSC8M oscillator
    GCLK->GENCTRL.reg           |= GCLK_GENCTRL_ID(0)
                                | GCLK_GENCTRL_GENEN
                                | GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSC8M_Val)
                                | GCLK_GENCTRL_OE;
    
    // SERCOM 0 peripheral ; clock generator 0
    GCLK->CLKCTRL.reg           |= GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val)
                                | GCLK_CLKCTRL_GEN(GCLK_CLKCTRL_GEN_GCLK0_Val)
                                | GCLK_CLKCTRL_CLKEN;
    
    // Synchronous bus clock without prescaler
    PM->APBCSEL.reg             |= PM_APBCSEL_APBCDIV(PM_APBCSEL_APBCDIV_DIV1_Val);
    
    // Enable SERCOM 0
    PM->APBCMASK.reg            |= PM_APBCMASK_SERCOM0;
}

void configure_spi_master(void){
    // Software reset
    SERCOM0->SPI.CTRLA.reg          |= SERCOM_SPI_CTRLA_SWRST;
    while(SERCOM0->SPI.CTRLA.bit.SWRST){};                  // Wait until reset
    
    // SPI master ; SPI frame format ; DIPO 0x0; DOPO 0x1
    SERCOM0->SPI.CTRLA.reg          |= SERCOM_SPI_CTRLA_MODE(SERCOM_SPI_CTRLA_MODE_SPI_MASTER_Val)
                                    | SERCOM_SPI_CTRLA_FORM(0)
                                    | SERCOM_SPI_CTRLA_DIPO(0)
                                    | SERCOM_SPI_CTRLA_DOPO(1);
    
    // Slave select low detect enable ; Master slave select enable
    SERCOM0->SPI.CTRLB.reg          |= SERCOM_SPI_CTRLB_SSDE
                                    | SERCOM_SPI_CTRLB_MSSEN;
    
     /*
     / Fix the baud rate at 1000000
     / SystemCoreClock / (2 * baudrate) - 1
     / SystemCoreClock = 8000000
     / baudrate = 1000000
    */
    SERCOM0->SPI.BAUD.bit.BAUD      = (SPI_LIGHTING_MAIN_CLK_FREQ) / (2 * (SPI_LIGHTING_BAUDRATE)) - 1;
    
    // Configure PIN DIPO
    PORT->Group[0].PINCFG[4].bit.PMUXEN = 0x1; // Enable peripheral multiplexing
    PORT->Group[0].PMUX[2].bit.PMUXE = SPI_LIGHTING_PERIPHERAL_MUX_EVEN;
    PORT->Group[0].PINCFG[4].bit.INEN = 0x1; // Enable input
    
    // Configure PIN SS
    PORT->Group[0].PINCFG[5].bit.PMUXEN = 0x1; // Enable peripheral multiplexing
    PORT->Group[0].PMUX[2].bit.PMUXO = SPI_LIGHTING_PERIPHERAL_MUX_ODD;
    
    // Configure PIN DOPO
    PORT->Group[0].PINCFG[6].bit.PMUXEN = 0x1; // Enable peripheral multiplexing
    PORT->Group[0].PMUX[3].bit.PMUXE = SPI_LIGHTING_PERIPHERAL_MUX_EVEN;
    
    // Configure PIN SCK
    PORT->Group[0].PINCFG[7].bit.PMUXEN = 0x1; // Enable peripheral multiplexing
    PORT->Group[0].PMUX[3].bit.PMUXO = SPI_LIGHTING_PERIPHERAL_MUX_ODD;
    
    // Enable SPI
    SERCOM0->SPI.CTRLA.reg          |= SERCOM_SPI_CTRLA_ENABLE;
    while(!(SERCOM0->SPI.CTRLA.reg & SERCOM_SPI_CTRLA_ENABLE)){};               // Wait until SPI is enabled
        
    NVIC_SetPriority(SERCOM0_IRQn, 3);                                  // Set the interrupt priority to 3 (lowest value)
    NVIC_EnableIRQ(SERCOM0_IRQn);                                       // Enable the interrupt
}

我得到的结果是LED的随机照明。对于我所得到的,我实在是再精确不过了。

我想我遗漏了一些关于从配置的东西,但我无法找到如何实现它。

知道吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-17 09:59:59

好吧..。我找到了一个可行的解决方案.如果你知道原因,请毫不犹豫地让我知道。

通过删除PMUX寄存器配置中的Select配置,一切都工作得很完美(不知道为什么.)。

我的SPI总线配置功能现在是:

代码语言:javascript
复制
#define SPI_LIGHTING_MAIN_CLK_FREQ    0x7A1200 // 8Mhz
#define SPI_LIGHTING_BAUDRATE         0xF4240  // 1000000

// Peripheral function D selected
#define USART_MIDI_PERIPHERAL_MUX_ODD     0x3
#define USART_MIDI_PERIPHERAL_MUX_EVEN    0x3

void configure_spi(void){
    // Software reset
    SERCOM0->SPI.CTRLA.reg            |= SERCOM_SPI_CTRLA_SWRST;
    while(SERCOM0->SPI.CTRLA.bit.SWRST){};                    // Wait until reset

    // SPI master ; SPI frame format ; DIPO 0x0; DOPO 0x1
    SERCOM0->SPI.CTRLA.reg            |= SERCOM_SPI_CTRLA_MODE(SERCOM_SPI_CTRLA_MODE_SPI_MASTER_Val)
                                      | SERCOM_SPI_CTRLA_FORM(0)
                                      | SERCOM_SPI_CTRLA_DIPO(0)
                                      | SERCOM_SPI_CTRLA_DOPO(1);

    // Slave select low detect enable ; Master slave selection enable
    SERCOM0->SPI.CTRLB.reg            |= SERCOM_SPI_CTRLB_MSSEN
                                      | SERCOM_SPI_CTRLB_SSDE;

     /*
     / Fix the baud rate at 1000000
     / SystemCoreClock / (2 * baudrate) - 1
     / SystemCoreClock = 8000000
     / baudrate = 1000000
    */
    SERCOM0->SPI.BAUD.bit.BAUD        = (float)(SPI_LIGHTING_MAIN_CLK_FREQ ) / (2 * (float)(SPI_LIGHTING_BAUDRATE )) - 1;

    // Configure PIN DIPO
    PORT->Group[0].PINCFG[4].bit.PMUXEN = 0x1;  // Enable peripheral multiplexing
    PORT->Group[0].PMUX[2].bit.PMUXE = SPI_LIGHTING_PERIPHERAL_MUX_EVEN;
    PORT->Group[0].PINCFG[4].bit.INEN = 0x1;    // Enable input

    // Configure PIN DOPO
    PORT->Group[0].PINCFG[6].bit.PMUXEN = 0x1; // Enable peripheral multiplexing
    PORT->Group[0].PMUX[3].bit.PMUXE = SPI_LIGHTING_PERIPHERAL_MUX_EVEN;

    // Configure PIN SCK
    PORT->Group[0].PINCFG[7].bit.PMUXEN = 0x1; // Enable peripheral multiplexing
    PORT->Group[0].PMUX[3].bit.PMUXO = SPI_LIGHTING_PERIPHERAL_MUX_ODD;

    // Enable SPI
    SERCOM0->SPI.CTRLA.reg            |= SERCOM_SPI_CTRLA_ENABLE;
    while(!(SERCOM0->SPI.CTRLA.reg & SERCOM_SPI_CTRLA_ENABLE)){};        // Wait until SPI is enabled

    NVIC_SetPriority(SERCOM0_IRQn, 3);                                   // Set the interrupt priority to 3 (lowest value)
    NVIC_EnableIRQ(SERCOM0_IRQn);                                        // Enable the interrupt
}
票数 1
EN

Stack Overflow用户

发布于 2022-05-18 09:28:54

很高兴你现在开始工作了:)至于为什么.我现在有了一个有条件的猜测,为什么原始代码不起作用。

我注意到有一个硅errata (我的浏览器说这个链接由于缺少https而不安全),它可能会导致虚假的/SS中断。

1.15.3SPI与从选低检测 如果在SSL检测启用(CTRLB.SSDE)和CTRLB.RXEN = 1的情况下,在SPI模式下启用了SERCOM,则会生成错误的从站选择低中断(INTFLAG.SSL)。 解决办法 首先使用CTRLB.RXEN = 0启用SERCOM。在后续的写入中,设置CTRLB.RXEN = 1。

影响硅修正: A,B,C,D,E。

您的初始代码使用了RXEN = 1,直到我在注释中问了为什么,所以在删除该部分之前,上面的勘误表可能会适用。

我不确定这是你问题的原因,但这是要记住的事情。检查您有哪些硅修订--当购买评估板时,通常会得到旧的硅,因为这样的板是很早就发布的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72258114

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档