avr-gcc为一个8位微控制器编译一些测试代码
const uint32_t N = 65537;
uint8_t values[N];
Run Code Online (Sandbox Code Playgroud)
我得到了以下编译警告(默认情况下应该是一个错误,真的)
warning: conversion from 'long unsigned int' to 'unsigned int' changes value from '65537' to '1' [-Woverflow]
uint8_t values[N];
Run Code Online (Sandbox Code Playgroud)
请注意,编译此目标时,sizeof(int)为2.
所以看来,在一个数组大小不能超过一个unsigned int.
我对么?这是GCC特定的还是某些C或C++标准的一部分?
在有人评论说8位微控制器通常没有足够的内存来容纳如此大的阵列之前,让我只是期待说这不是重点.
我在嵌入式环境(Arduino/AVR ATMega328)中工作,并希望在C++中实现Factory Method模式.但是,我正在使用的编译器(avr-gcc)不支持该new关键字.有没有办法在不使用的情况下实现这种模式new?
I would like to know if performing a logical right shift is faster when shifting by a power of 2
For example, is
myUnsigned >> 4
Run Code Online (Sandbox Code Playgroud)
any faster than
myUnsigned >> 3
Run Code Online (Sandbox Code Playgroud)
我很欣赏每个人的第一反应是告诉我,人们不应该担心像这样的小事,它使用正确的算法和集合来减少重要的数量级.我完全同意你的意见,但我真的想从嵌入式芯片(ATMega328)中挤出所有东西 - 我只是有一个性能转变,值得'哇喔!' 通过用位移替换除法,所以我向你保证这很重要.
我读过在某些情况下(全局变量,或while(变量)等),如果未定义变量volatile,可能会导致问题.
如果我将所有变量定义为volatile,会导致问题吗?
我认为许多Arduino/AVR MCU的程序员可以分享一些知识.
我的具体问题是:
在Atmel Atmega128 AVR的情况下.
基于ADC数据,我正在运行一个循环,它正在对串行控制台进行一些计算,它也驱动了一个中断.
发生的事情是,当我使用一定数量的串行输出时,程序突然变得非常不稳定.
代码中的随机跳转,随机未知中断,随机变量损坏,无MCU寄存器位设置的随机复位.
在特定点添加缓冲区解决了不稳定性.
更改gcc的优化参数也改变了行为,没有优化,代码非常稳定.
检查我的答案可能的原因和真正的原因.
我正在尝试在ATmega2560上使用硬件PWM,使用TC0(一个8位定时器),在快速PWM模式下.我需要动态调整占空比,这包括零占空比.然而,这似乎并不容易,甚至不可能.引用数据表:
OCR0A寄存器的极值表示在快速PWM模式下生成PWM波形输出时的特殊情况.如果OCR0A设置为BOTTOM,则每个MAX + 1定时器时钟周期的输出将为一个窄峰值.将OCR0A设置为MAX将导致恒定的高或低输出(取决于COM0A1:0位设置的输出的极性).
因此,将OCR0A设置为0(= BOTTOM)实际上不会导致占空比为零,我的测试证实了这一点.还需要采取其他一些方法.
首先,我已经教过如上所述使用OCR0A = MAX特殊情况.结合暂时切换到反转模式,这将导致零占空比.但是,由于COM0A1:0不是双缓冲(并且不与OCR0A同步),如果在输出为高电平时切换模式,这可能会导致输出出现毛刺(在下一次溢出之前它将保持高电平) ).OCR0A改变和模式改变的顺序似乎并不重要,两者都可能出现故障.
我还考虑了另一种解决方案,通过设置COM0A1来关闭PWM:0 = 0.这将立即将输出设置为PORT寄存器中的值,该值为零.但是仍然存在从零输出回到非零占空比的问题.根据我在数据表中的描述,设置COM0A1:0以重新使能PWM将立即将输出引脚切换到PWM的输出,这可能是一个不正确的值,直到下一个比较匹配或定时器溢出.因此,一个小故障.
总体上反转PWM可能是适用的,但是问题恰好变为完全占空比,具有对称问题.
请注意,在通过PORT强制引脚输出时,不能启用PWM波形生成,如数据表中所述:
比较输出模式(COM0x1:0)位有两个功能.波形发生器使用COM0x1:0位在下一个比较匹配时定义输出比较(OC0x)状态.此外,COM0x1:0控制OC0x引脚输出源.
没有办法让PWM运行一个周期左右,并在它准备就绪时切换到它 - 使能PWM立即强制引脚输出.
UPDATE.相位校正(中心对齐)PWM模式没有这个问题,在我的情况下是可以接受的.我已经尝试过并确认它适用于零占空比和全占空比.
是否有一种简单的方法可以使用用于Arduino IDE的库以及我为AVR-G ++/AVR-GCC编写的C和汇编代码?
我正在尝试使用Adafruit Wave Shield库,但只是包含头文件和cpp文件并没有太大的帮助.我可以以某种方式编译它并将其链接到我的C代码?或者也许只是找到一种方法来使用我的C代码进行编译.
目前,当我尝试做一些简单的事情时:
#include "WaveHC/WaveHC.h"
SdReader card;
card.init();
Run Code Online (Sandbox Code Playgroud)
我受到了欢迎:
70: undefined reference to `SdReader::init(unsigned char)'
Run Code Online (Sandbox Code Playgroud) 我想了解更多有关Arduino Nano计时器的信息.
delay()和delayMicroseconds()实施...
我有一个非常简单的中断服务程序(ISR)为atmega328编写,并使用AVR工作室使用avrgcc(使用-Os)编译.
ISR (TIMER0_OVF_vect) {
txofcnt++; //count overflows and store in uint16_t
}
Run Code Online (Sandbox Code Playgroud)
如果你注意到生成的程序集(如下),它使用r24,r25来获取增加易失性uint16_t txofcnt的作业,但它也是push-write-pop r1,r28,r29而没有读取它们.它还有一个额外的r0推/弹,而不会在它们之间使用它.
我不知道为什么r1被推,清除然后最终poped.但是为什么gcc觉得需要将EIMSK和GPIOR0加载到寄存器中然后不使用它们.如果你能告诉我GPIOR0的用途是什么,那么数据表说它存在但没有描述.
00000258 <__vector_16>:
ISR (TIMER0_OVF_vect) {
258: 1f 92 push r1
25a: 0f 92 push r0
25c: 00 90 5f 00 lds r0, 0x005F
260: 0f 92 push r0
262: 11 24 eor r1, r1
264: 8f 93 push r24
266: 9f 93 push r25
268: cf 93 push r28
26a: df 93 push r29
26c: cd b7 in r28, 0x3d ; 61 reads register …Run Code Online (Sandbox Code Playgroud) 我正在使用Atmega328在SD卡上实现FAT16.
我经常需要更改扇区中的一个或两个字节(512B区域).
我知道Flash是如何工作的,它需要立刻覆盖整个扇区,但我想知道是否有一些特殊的命令可以使卡本身处理它?
关键是,atmega只有2k RAM,而且只为读取 - 修改 - 写入SD卡缓冲区分配512是非常不利的.没有其他办法吗?
(PS.AFAIK atmega本身不能有外部ram)