【发布时间】:2022-11-16 05:04:30
【问题描述】:
我目前正在 SAMD51 板中配置 SPI 通信。经过大量研究,我找到了如何设置寄存器以启动引脚配置和时钟设置等。但是在设置结束时有一个过程需要再次启用该引脚。
这是 MCU https://www.mouser.com/datasheet/2/268/60001507A-1130176.pdf 的数据表
SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
在我调用这条线之后,图书馆冻结了,我无法得到任何其他回应。
在 cpp 文件下方找到。
#include "SercomSPISlave.h"
// Constructors //
SercomSPISlave::SercomSPISlave()
{
}
// Public Methods //
void SercomSPISlave::Sercom4init()
{
//Setting up NVIC
NVIC_EnableIRQ(SERCOM4_0_IRQn);
NVIC_SetPriority(SERCOM4_0_IRQn,2);
//MCLK->APBDMASK.reg |= MCLK_APBDMASK_SERCOM4;
MCLK->APBDMASK.bit.SERCOM4_ = 1;
//Setting Generic Clock Controller!!!!
//GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM4_CORE) | //Generic Clock 0
// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
// GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator
GCLK->PCHCTRL[34].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
//while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation
//Configure SERCOM4 SPI PINS
//Set PA12 as input (MOSI) - on D22 / MISO
//Set PB09 as input (SCK) - on A2
//Set PB10 as input (SS) - on D23 / MOSI
//Set PB11 as output (MISO) - on D24 / SCK
PORT->Group[PORTB].PINCFG[11].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB11
PORT->Group[PORTB].PMUX[11 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTB].PINCFG[12].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB12
PORT->Group[PORTB].PMUX[12 >> 1].bit.PMUXE = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTB].PINCFG[13].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB13
PORT->Group[PORTB].PMUX[13 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTA].PINCFG[9].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB09
PORT->Group[PORTA].PMUX[9 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
/*
Explanation:
PMUXEN stands for Peripheral Multiplexing Enable
PMUXE stands for Even bits in the Peripheral Multiplexing register
PMUXO stands for Odd bits in the Peripheral Multiplexing register
The selection of peripheral function A to H is done by writing to the Peripheral Multiplexing Odd and Even bits in the Peripheral Multiplexing register (PMUXn.PMUXE/O) in the PORT.
Reference: Atmel-42181G-SAM-D21_Datasheet section 6.1 on page 21
PA12 corresponds to: PORTA, PMUX[6] Even
PB09 corresponds to: PORTB, PMUX[4] Odd
PB10 corresponds to: PORTB, PMUX[5] Even
PB11 corresponds to: PORTB, PMUX[5] Odd
In general:
Px(2n+0/1) corresponds to Portx, PMUX[n] Even=0/Odd=1*/
//Disable SPI 1
SERCOM4->SPI.CTRLA.bit.ENABLE =0;
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
//Reset SPI 1
SERCOM4->SPI.CTRLA.bit.SWRST = 1;
while(SERCOM4->SPI.CTRLA.bit.SWRST || SERCOM4->SPI.SYNCBUSY.bit.SWRST);
//Set up SPI Control A Register
SERCOM4->SPI.CTRLA.bit.DORD = 0; //MSB first
SERCOM4->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
SERCOM4->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
SERCOM4->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
SERCOM4->SPI.CTRLA.bit.DIPO = 0x0; //DATA PAD0 MOSI is used as slave input (slave mode) // page 492
SERCOM4->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD2 MISO is used as slave output
SERCOM4->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
SERCOM4->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
SERCOM4->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
//Set up SPI control B register
//SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
SERCOM4->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
SERCOM4->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM4->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//while (SERCOM4->SPI.SYNCBUSY.bit.CTRLB);
//Set up SPI interrupts
SERCOM4->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM4->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM4->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while(SERCOM4->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled
Serial.begin(115200);
SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
Serial.print(SERCOM4->SPI.CTRLA.bit.ENABLE);
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
}
在 .h 文件下方找到。
#ifndef SercomSPISlave_h
#define SercomSPISlave_h
#include <Arduino.h>
class SercomSPISlave
{
public:
// Constructors //
SercomSPISlave();
// Public Methods //
void Sercom4init();
};
#endif
在 .ino 代码下方找到
#include <SercomSPISlave.h>
SercomSPISlave SPISlave;
void setup()
{
Serial.begin(115200);
Serial.println("Serial started");
SPISlave.Sercom4init();
while(!Serial);
Serial.println("Sercom1 SPI slave initialized!");
}
void loop()
{
}
我感谢你能给我的任何支持。
【问题讨论】:
-
我推荐阅读文章"SAM D21 SERCOM SPI Configuration"。如果您选择不在寄存器级别控制 SPI 模块,请阅读文章"Adding More SERCOM Ports for SAMD Boards"。
-
如果您希望寄存器级控制将 SPI 功能分配给不同的引脚,请再次查看这些代码:sercom.h、sercom.cpp
-
阅读文章"Advanced Debugger for Arduino"一步步调试。
-
要了解问题发生的原因,您需要排除许多因素并更清楚地提出问题。