这应该是一个简单的公式,但我无法弄清楚.
我有一个16mHZ的AVR芯片.
我需要运行一个PWM信号为24kHZ ..
什么是决定什么是最好的预分频器的公式.
我使用的是16位定时器.
为什么以下代码在Arduino中不起作用?
#include<avr/io.h>
void setup()
{
DDRA = 0xFF;
}
void loop()
{
PORTA = 0xAA;
_delay_ms(1000);
PORTA = 0x55;
_delay_ms(1000);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误."DDRA未在此范围内宣布."
据我所知,arduino使用AVR微控制器,为什么我们不能在arduino板上使用AVR代码呢?
我正在使用Visual Studio 2013为AVR编写代码.我一直在关注这个教程.
在编写代码的同时,我注意到Visual Studio继续强调像DDRB或者这样的东西,PORTB并且我继续得到错误Error: identifier "PORTB" is undefined,但是,程序正确编译.
有趣的是,在按下alt- F12视觉发现它们被定义了许多文件.
我有一个使用 Arduino Uno 的项目,我需要存储一个对于 EPROM 来说太大的字符**。
我目前正在尝试使用串口来完成此操作,但如果需要的话我也可以使用 AVRISP 程序员(不推荐)
到目前为止,我已经研究了 avr/boot.h API,但我不太确定如何正确使用它,或者它是否是正确的方法。
我想使用 IO 寄存器(== 静态内存地址)作为模板参数。问题是,寄存器通常被定义为宏扩展到类似的东西(*(volatile uint8_t*)(11 + 0x20)),我不知何故无法正确使用我的模板。
我想编写如下代码:
Foo<PORTB> foo;
Run Code Online (Sandbox Code Playgroud)
这样我就可以轻松更改类使用的 IO 寄存器,而无需任何运行时开销(这对微控制器至关重要)。我在下面包含了一个完整的例子:
#include <stdint.h>
#include <stdio.h>
#include <utility>
#define PORTB (*(volatile uint8_t*)(11 + 0x20))
template<volatile uint8_t* PortRegister>
class ControllerPtr final
{
public:
static void SetHigh() { *PortRegister |= 0x2; }
};
template<volatile uint8_t& PortRegister>
class ControllerRef final
{
public:
static void SetHigh() { PortRegister |= 0x2; }
};
int main()
{
ControllerPtr<&PORTB> ptr;
ControllerRef<PORTB> ref;
ptr.SetHigh();
ref.SetHigh();
// Both statements should be equal to:
// PORTB |= …Run Code Online (Sandbox Code Playgroud) 我正在编译一个8位AVR微控制器(AVR-GCC)的应用程序.为了减少微控制器中的闪存使用,链接器必须仅链接应用程序代码使用的函数.我正在编写自己的库,我发现了以下声明.
"为每个代码模块编写一个函数.这将编译为每个对象模块一个函数" - 来源:http://nongnu.org/avr-libc/user-manual/library.html
这是什么意思?如何为每个函数创建单独的目标文件?现在我的库中只有一个.h文件和一个.c文件.
我正在查看编译后编写的一些代码的生成程序集avr-gcc。具体来说,我是用-Os选项编译的。总的来说,输出是我所期望的,但我无法理解的是push r1正在发出的指令。更奇怪的是,函数末尾的补充指令是pop r0. 所以 的值r1正在被保存但它似乎被恢复到r0
根据此处的文档:
https://gcc.gnu.org/wiki/avr-gcc#Register_Layout
寄存器r1始终包含零,但函数可以在恢复寄存器时使用该寄存器。恢复它将是ldi r1, 0x0,不需要推动,从我的理解中弹出。
下面是编译版本的 C 代码和反汇编示例。它是用-Os. 它有点长,但我必须制作一个大函数才能让编译器发出它。
代码:
void mqtt_create_connect(mqtt_parser *p, mqtt_connect_config *cfg){
uint8_t idx = 0;
p->buffer[idx++] = MQTT_CTRL_CONNECT << 4;
idx++; // skip remaining length for now
p->buffer[idx++] = 0x0;
p->buffer[idx++] = 0x4;
p->buffer[idx++] = 'M';
p->buffer[idx++] = 'Q';
p->buffer[idx++] = 'T';
p->buffer[idx++] = 'T';
p->buffer[idx++] = 0x04; // protocol level 3.1.1
p->buffer[idx++] = …Run Code Online (Sandbox Code Playgroud) 根据 AVR 微控制器的数据表以及 AVR 架构的指令集数据表,某些指令,例如ADD,可以在仅 1 个时钟转换到 ALU 期间获取存储在 GP 寄存器中的 2 个操作数。指令的指令字ADD包括 2 个 GP 寄存器地址;每个 5 位宽,一个用于目标/源,一个用于源。但是这是如何在硬件级别上实现的呢?当他们试图通过相同的直接寻址总线访问 GP 寄存器时,2 个寄存器的 5 位不会相互干扰吗?
在我的一个程序中,我收到错误
invalid conversion from 'void* (*)()' to 'void*' [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
我试图了解这两种数据类型之间的区别。这很令人困惑。
我认为这些数据类型是:
void* (*)()所以这个数据类型是一个指向 void ( void*)的指针,它还有另一个指针 ( (*)),并且出于某种奇怪的原因,它有空括号。所以我想象的这种数据类型的内存看起来像|--void address--|--pointer of unknown type--|--something denoting no arguments--|
然后是void*。这看起来很简单,它只代表一个函数的地址。内存模型应该像|--void address--|.
为什么这么奇怪,是抛出错误的函数如下。
void callFunction(void *voidThing){
void *testVariable = voidThing;
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这会创建一个指针类型的 testVariable,并且该指针指向 void。该函数还接受一个指针类型的参数,该指针也指向 void。
为什么编译器会抛出错误,即使局部变量与参数类型相同?就两者的内存占用而言,变量之间有什么区别?
我是如何为嵌入式软件测试一些特定的 C 宏的。
例如,如果我有以下宏:
/*
Set a pin as an input
port (B,C, D or E)
pin - pin to set (0-7)
*/
#define _SET_INPUT_PIN(port,pin) DDR ## port &= ~(1<<pin)
#define SET_INPUT_PIN(...) _SET_INPUT_PIN(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
我想用两个端口测试它,一个存在(LED_OK)另一个不存在(LED_FAIL):
#define LED_OK D,3
#define LED_FAIL D,8
Run Code Online (Sandbox Code Playgroud)
当我尝试测试它时,LED_OK 和 LED_FAIL 都可以正常工作,但某种警告/失败应该提醒 LED_FAIL 不存在,因为 PORTD 只定义了引脚 0 到 7。
那么,当我通过LED 时,如何检查“ pin ”是否在范围内?