我只想向您提供 LED 闪烁的示例(1000 毫秒中有 1 次)。我的微控制器是 ATmega328P,我使用的是 Atmel Studio。
状态 1:如果我不定义F_CPU,则 LED 闪烁运行为 true。我使用默认熔丝设置(内部振荡器和 CKDIV8=已编程)。
状态 2:如果我定义F_CPU 8000000UL,LED 闪烁的运行速度会慢 8 倍,并且我再次使用默认熔丝设置(内部振荡器和 CKDIV8=已编程)。
我在 1.state 和 2.state 中都不使用外部晶体。和相同的保险丝设置。为什么我会看到这个结果?为什么慢8倍?
问题2:有些库需要F_CPU价值,比如UART。我不使用外部振荡器。我应该为这个值写什么?
我在 Arduino IDE 中有两个文件。一种是.ino文件,一种是.c文件。
main.ino:
#include "somefile.c"
void setup(){
Serial.begin(9600);
// Do something
}
void loop(){
// Do something
}
Run Code Online (Sandbox Code Playgroud)
并在somefile.c我想打电话Serial.print()。我怎样才能做到这一点?谢谢!
我有一个名为USB AVR JTAG-ISP v.1.2的编程设备.
我在哪里可以找到驱动程序和一个好的IDE?
我目前正在阅读有关avr汇编程序编程的教程.有说:
位操作cbr和sbr清除或设置寄存器中的一个多位.这些指令仅适用于寄存器r16至r31.它们不使用单个位作为参数,而是使用可包含多个位的掩码:
sbr r16, (1<<5)+(1<<3) ;set bits 5 and 3 in register 16
cbr r16,0x03 ;clear bits 1 and 0 in register 16
Run Code Online (Sandbox Code Playgroud)
谁能解释一下这两条指令的参数?为什么我要写(1 << 5)+(1 << 3)才能设置第5和第3位?我猜<<就像一个位移操作.
感谢您抽出宝贵时间阅读.
我遇到的问题
我有:
main.h
Run Code Online (Sandbox Code Playgroud)
声明:
uint8_t u_newVar
Run Code Online (Sandbox Code Playgroud)
我也有
foo.h
Run Code Online (Sandbox Code Playgroud)
写道:
extern uint8_t u_newVar
Run Code Online (Sandbox Code Playgroud)
应用程序位于main.c中的无限while循环中,直到出现ISR.
在foo.c中,所述ISR在foo.c中调用一个函数.
在该函数中(如果你愿意,则为foo_function()):0x01被写入u_newVar.
最后,从中断返回到无限时,有一个"if"语句:
while(1){
if(u_newVar == 0x01){
uartTX_sendArray(st_uartRX_MessageContents->u_command, (sizeof st_uartRX_MessageContents->u_command));
uartTX_sendButtonPressData(st_uartRX_MessageContents->u32_value);
u_newVar = 0x00;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,应用程序永远不会进入if.如果它位于foo.c之后,这个"if"块将起作用
u_newVar = 0x01;
Run Code Online (Sandbox Code Playgroud)
线.
我试过的东西
我看着编译过的集合,我发现了什么样的东西让我感到难过.
如果我看一下main中的"if",这就是我所看到的:

因此它从SRAM中加载地址:0x011D的值,我可以确认它是0x01.
然后"CPI"将R24直接与0x01进行比较,这显然应该可行.
然后是"BREQ",如果相等则分支,并将程序计数器增加两次到下面的uart函数.也有道理.
然而这部分很奇怪.否则,使用"RJMP"跳转到当前所在的指令.除非我弄错了,否则这将永远锁定在这里?
那么,还记得当我提到在写入u_newVar之后将if块放入foo.c时吗?是的,这不是太有趣:

"if"应该在"u_newVar = 0x01"之后,但编译器太聪明并且如何优化它.这就是它始终在那里工作的原因.
请帮忙.我的程序只运行一次while循环:(
我不知道问题是什么.我在python中编写了同样的东西,并且在那里工作得很好.
我是C的初学者,我正在使用Atmel的AtMega8微处理器.
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRD = 0xFF;
int world[9];
int nextworld[9];
//from 1 to 8
//some random start values
world[1] = 1;
world[2] = 1;
world[3] = 1;
world[6] = 1;
world[7] = 1;
world[8] = 1;
for (int i = 0; i < 9; i++) {
nextworld[i] = world[i];
}
int binworld = 0;
int tiles = 0;
//=============================
if (world[1] == 1) {
binworld = binworld + 128;
} …Run Code Online (Sandbox Code Playgroud) 该线定义了avr微控制器中DDRD寄存器的地址
#define myDDRD *((volatile unsigned char* const) 0x31)
Run Code Online (Sandbox Code Playgroud)
你能澄清一下如何在上面的行中使用指针吗?为什么我们需要第一个星号?不应该第二个足以指向地址0x31?
我知道这很接近于"愚蠢问题"类别,但我一直在研究如何在AVR 8-bit上启动加载后执行机器代码,并且已经了解到AVR 8上使用的哈佛架构 - 位MCU使得无法从闪存以外的任何地方执行代码.那么如何使用内联asm在运行时引入新的可执行代码呢?
我必须编写一个程序,可以从地址0x0200开始,在SRAM中存储从11到40开始的连续整数.
这是我在汇编语言中尝试做的事情:
LDI R16, 10
LDI R17, 30
.EQU MEM = 0x0200
L1: INC R16
STS MEM, R16
INC MEM
DEC R17
BRNE L1
L2: jmp L2
Run Code Online (Sandbox Code Playgroud)
但是,Atmel Studio不允许我递增地址.没有必须输入30个STS,有没有解决这个问题的方法?
让我们考虑为atmega32编译的以下简单C代码:
_delay_ms(1000);
Run Code Online (Sandbox Code Playgroud)
它被翻译成以下程序集:
00000039 SER R18 Set Register
0000003A LDI R24,0x69 Load immediate
0000003B LDI R25,0x18 Load immediate
0000003C SUBI R18,0x01 Subtract immediate
0000003D SBCI R24,0x00 Subtract immediate with carry
0000003E SBCI R25,0x00 Subtract immediate with carry
0000003F BRNE PC-0x03 Branch if not equal
00000040 RJMP PC+0x0001 Relative jump
00000041 NOP No operation
Run Code Online (Sandbox Code Playgroud)
当这行:
_delay_ms(500);
Run Code Online (Sandbox Code Playgroud)
编译为此:
00000039 SER R18 Set Register
0000003A LDI R24,0x34 Load immediate
0000003B LDI R25,0x0C Load immediate
0000003C SUBI R18,0x01 Subtract immediate
0000003D SBCI R24,0x00 Subtract …Run Code Online (Sandbox Code Playgroud)