电子说
步骤1:生成正弦数据数组
由于实时计算对CPU的要求很高,因此需要一个正弦数据数组以获得更好的性能
uint32_t sin768 [] PROGMEM = 。..。
而x = [0:5375]; y = 127 + 127 *(sin(2 * pi/5376/*或您希望根据要求使用一些#*))
步骤2:启用并行输出
与Uno不同,Due具有有限的参考。但是,要基于Arduino Uno生成三相正弦波,首先,由于其MCLK低(16MHz,而Due是84MHz),因此性能不佳,第二,它的GPIO有限,可以产生最大2相输出,您需要额外的模拟电路产生第三相(C = -AB)。
启用GPIO的步骤主要是基于SAM3X的try and trial +无用数据表
PIOC-》 PIO_PER = 0xFFFFFFFE ;//PIO控制器PIO使能寄存器(请参阅ATMEL SAM3X数据表的p656)和http://arduino.cc/zh-CN/Hacking/PinMappingSAM3X、Arduino Due引脚33-41和44-51已启用
PIOC-》 PIO_OER = 0xFFFFFFFE;//PIO控制器输出使能寄存器,请参见ATMEL SAM3X数据手册p657-》 PIO_OSR = 0xFFFFFFFE;//PIO控制器输出状态寄存器,请参阅ATMEL SAM3X数据表的p658
PIOC-》 PIO_OWER = 0xFFFFFFFE;//PIO输出写使能寄存器,请参阅ATMEL SAM3X数据表的p670
//PIOA-》 PIO_PDR = 0x30000000;//作为保险是可选的,似乎并不影响性能,数字引脚10连接到PC29和PA28,数字引脚4连接到PC29和PA28,此处禁用禁用PIOA#28&29
步骤3:启用中断
为最大程度地发挥其性能,CPU负载应尽可能低。但是,由于CPU引脚和Due引脚之间的非1to1对应关系,需要进行位操作。
您可以进一步优化算法,但空间非常有限。
void TC7_Handler(void)
{TC_GetStatus(TC2,1);
t = t%样本;//使用t%samples而不是‘if’来避免t的溢出
phaseAInc =(preset * t)%5376;//使用%5376避免数组索引溢出
phaseBInc =(phaseAInc + 1792)%5376;
phaseCInc =(phaseAInc + 3584)%5376;
p_A = sin768 [phaseAInc] 《《1;//参考PIOC:PC1至PC8,对应的Arduino Due引脚:引脚33-40,因此向左移1位
p_B = sin768 [phaseBInc] 《《12;//参考PIOC:PC12至PC19,对应的Arduino Due引脚:引脚51-44,因此左移12位
p_C = sin768 [phaseCInc];//C相输出使用PIOC:PC21,PC22,PC23,PC24,PC25,PC26,PC28和PC29,对应的Arduino Due引脚:数字引脚:分别为9,8,7,6,5,4,3,10
p_C2 =(p_C&B11000000)《《22;//这会生成PC28和PC29
p_C3 =(p_C&B00111111)《《21;//这会生成PC21-PC26
p_C = p_C2 | p_C3;//这会产生C相的并行输出
p_A = p_A | p_B | p_C;//32位输出= A相(8位)| B相| C相
PIOC-》 PIO_ODSR = p_A;//输出寄存器= p_A
t ++; }
第4步:R/2R DAC
构建3x8bit R/2R DAC,在Google上加载参考。
步骤5:完整代码
#define _BV(x)(1 《《(x));
uint32_t sin768 [] PROGMEM =/* x = [0:5375 ]。 y = 127 + 127 *(sin(2 * pi/5376))*/
uint32_t p_A,p_B,p_C,p_C2,p_C3;//A相B相C值-尽管输出仅8位,但p_A和p_B值将被操作以生成新的32位值,以应对32位PIOC输出
uint16_t phaseAInc,phaseBInc ,phaseCInc,freq,freqNew; uint32_t间隔; uint16_t个样本,预设; uint32_t t = 0;
void setup(){
//并行输出PIOC设置:Arduino Due引脚33-40被用作A相输出,而44-51引脚则用于A相B输出
PIOC-》 PIO_PER = 0xFFFFFFFE;//PIO控制器PIO使能寄存器(请参阅ATMEL SAM3X数据表的p656)和http://arduino.cc/zh-CN/Hacking/PinMappingSAM3X、Arduino Due引脚33-41和44-51已启用
PIOC-》 PIO_OER = 0xFFFFFFFE;//PIO控制器输出使能寄存器,请参阅ATMEL SAM3X数据表的p657
PIOC-》 PIO_OSR = 0xFFFFFFFE;//PIO控制器输出状态寄存器,请参阅ATMEL SAM3X数据表的p658
PIOC-》 PIO_OWER = 0xFFFFFFFE;//PIO输出写使能寄存器,请参阅ATMEL SAM3X数据表的p670
//PIOA-》 PIO_PDR = 0x30000000;//作为保险,是可选的,似乎不影响性能,数字引脚10连接到PC29和PA28,数字引脚4连接到PC29和PA28,此处禁用禁用PIOA#28和29//定时器设置,请参阅http ://arduino.cc/en/Hacking/PinMappingSAM3X,
pmc_set_writeprotect(false);//禁用电源管理控制寄存器的写保护
pmc_enable_periph_clk(ID_TC7);//启用外设时钟时间计数器7
TC_Configure(/*时钟*/TC2,/*通道*/1,TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);//TC时钟42MHz(时钟,通道,比较模式设置)TC_SetRC(TC2,1,interval); TC_Start(TC2,1);
//在计时器TC2-》 TC_CHANNEL [1]上启用计时器中断。TC_IER= TC_IER_CPCS;//IER =中断允许寄存器TC2-》 TC_CHANNEL [1] .TC_IDR =〜TC_IER_CPCS;//IDR =中断禁止寄存器
NVIC_EnableIRQ(TC7_IRQn);//在嵌套向量中断控制器freq = 60中启用中断;//将频率初始化为60Hz预设= 21;//数组索引增加21个样本= 256;//输出样本256/周期间隔= 42000000/(频率*样本);//中断计数TC_SetRC(TC2,1,interval);//启动TC Serial.begin(9600);//出于测试目的}
void checkFreq()
{freqNew = 20000;
if(freq == freqNew){}其他
{freq = freqNew;
if(freq》 20000){freq = 20000;/*最大频率20kHz */};
,如果(freq 《1){freq = 1;/*最低频率1Hz */};
如果(freq》 999){preset = 384;样本= 14;}//对于频率》 = 1kHz,每个周期14样本
否则(freq》 499){preset = 84;样本= 64;}//对于500 《=频率《1000Hz,每个周期64个样本,否则(freq》 99){preset = 42; samples = 128;}//对于100Hz 《= frequency 《500Hz,128个采样/周期
else {preset = 21;样本= 256;};//对于频率《100hz,每个周期256个采样
间隔= 42000000/(freq * samples); t = 0; TC_SetRC(TC2,1,间隔); }}
void loop(){
checkFreq();延迟(100); }
void TC7_Handler(void)
{TC_GetStatus(TC2,1);
t = t%样本;//使用t%samples引起t phase的溢出AInc =(preset * t)%5376;//使用%5376避免数组索引溢出
phaseBInc =(phaseAInc + 1792)%5376;
phaseCInc =(phaseAInc + 3584)%5376;
p_A = sin768 [phaseAInc] 《《1;//参考PIOC:PC1至PC8,对应的Arduino Due引脚:引脚33-40,因此向左移1位
p_B = sin768 [phaseBInc] 《《12;//参考PIOC:PC12至PC19,对应的Arduino Due引脚:引脚51-44,因此左移12位
p_C = sin768 [phaseCInc];//C相输出使用PIOC:PC21,PC22,PC23,PC24,PC25,PC26,PC28和PC29,对应的Arduino Due引脚:数字引脚:分别为9,8,7,6,5,4,3,10
p_C2 =(p_C&B11000000)《《22;//这会生成PC28和PC29
p_C3 =(p_C&B00111111)《《21;//这将生成PC21-PC26//Serial.println(p_C3,BIN); p_C = p_C2 | p_C3;//这会产生C相的并行输出
p_A = p_A | p_B | p_C;//32位输出= A相(8位)| B相| C相////Serial.println(p_A》》21,BIN);//PIOC-》 PIO_ODSR = 0x37E00000;
PIOC-》 PIO_ODSR = p_A;//输出寄存器= p_A t ++; }
责任编辑:wv
全部0条评论
快来发表一下你的评论吧 !