Apologies if I have the incorrect forum or topic.
I am running the Arduino IDE with Arduino with Arduino Mbed OS RP2040 support for the Raspberry Pi installed.
I am using Alarms to provide a timed interrupt as per this blog ( Raspberry Pi Pico, Arduino Core and Timers – Kevin's Blog ). That all works fine and I can toggle a digital out to get a nice fast square wave.
However I am trying to use SPI to drive a MCP4922 DAC with the following code (and a SPI.begin() in the setup:
‘‘int DAC = 8;
void mcpWrite(int value, int Channel) {
//set top 4 bits of value integer to data variable
byte data = value >> 8;
data = data & 0b00001111;
if (Channel == 0)
data = data | 0b00110000; //DACA Bit 15 Low
else
data = data | 0b10110000; //DACB Bit 15 High
digitalWrite(DAC, LOW); //CS
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
SPI.transfer(data);
data = value;
SPI.transfer(data);
SPI.endTransaction();
digitalWrite(DAC, HIGH);
}’’
Now, if I put this in the loop it works fine. However, if I put this in the interrupt routine, the code fails and the system hangs ( the inbuilt LED flashes a pattern oddly). Is there a reason SPI and Alarms don’t function nicely together? Hopefully, someone has an idea .
Regards
Andy
Full code here:
#include <hardware/timer.h>
#include <hardware/irq.h>
#include “SPI.h”
#define ALARM_NUM 1
#define ALARM_IRQ TIMER_IRQ_1
#define ALARM_FREQ 1250
uint32_t alarmPeriod;
int DAC = 8;
void mcpWrite(int value, int Channel) {
//set top 4 bits of value integer to data variable
byte data = value >> 8;
data = data & 0b00001111;
if (Channel == 0)
data = data | 0b00110000; //DACA Bit 15 Low
else
data = data | 0b10110000; //DACB Bit 15 High
digitalWrite(DAC, LOW); //CS
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
SPI.transfer(data);
data = value;
SPI.transfer(data);
SPI.endTransaction();
digitalWrite(DAC, HIGH);
}
const float Pi = 3.14159;
const float twoPi = 2.0 * Pi;
float theta = 0.0;
float delta = twoPi / 100;
float Val = 0.0;
int ledval;
int WaveOut = 0;
uint32_t MaxCount = 10;
uint32_t Count = 0;
static void alarm_irq(void) {
ledval = !ledval;
digitalWrite(7, ledval);
if (Count == 0) {
WaveOut = !WaveOut;
digitalWrite(9, WaveOut);
Val = 0.5 * sin(theta) + 0.5;
mcpWrite(4095*Val , 0);
theta = theta + delta;
if (theta > twoPi)
theta = 0;
}
Count++;
if (Count == MaxCount)
Count = 0;
hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM);
alarm_in_us_arm(alarmPeriod);
}
static void alarm_in_us_arm(uint32_t delay_us) {
uint64_t target = timer_hw->timerawl + delay_us;
timer_hw->alarm[ALARM_NUM] = (uint32_t) target;
}
static void alarm_in_us(uint32_t delay_us) {
hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM);
irq_set_exclusive_handler(ALARM_IRQ, alarm_irq);
irq_set_enabled(ALARM_IRQ, true);
alarm_in_us_arm(delay_us);
}
void setup () {
pinMode(DAC, OUTPUT);
pinMode (7, OUTPUT);
pinMode (9, OUTPUT);
pinMode (LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
SPI.begin();
Serial.println(MOSI);
Serial.println(MISO);
Serial.println(SCK);
Serial.end();
alarmPeriod = 1000000 / ALARM_FREQ;
alarm_in_us(alarmPeriod);
mcpWrite(4095, 0);
}
int ledval2;
void loop () {
ledval2 = !ledval2;
digitalWrite(LED_BUILTIN, ledval2);
}