我想为Atmel ATMega32U4实现与Arduino的引脚号类似的东西。我看过Arduino的digitalWrite
命令和相关的源文件,看看它们是如何做的,但我认为这有点复杂,所以我想实现一个更基本的版本。在AVR微控制器中实现类似于Arduino的引脚号
这个想法是有整数1到n代表AVR芯片上的每个I/O引脚。我开始用指针数组的DDR/PORT寄存器,其中该指数将代表销地址:
volatile uint8_t *pin_port_dir_regs[] = {
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&DDRE, // PIN_7
&DDRB, // PIN_8
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&DDRB, // PIN_15
&DDRB // PIN_16
};
volatile uint8_t *pin_port_out_regs[] = {
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&PORTE, // PIN_7
&PORTB, // PIN_8
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
0, // NOT USED
&PORTB, // PIN_15
&PORTB // PIN_16
};
我还需要在每一个的DDRx/PORTx寄存器的知道比特数,所以我创造了另一个数组:
const uint8_t pin_bits[] = {
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(6), // PIN_7
_BV(4), // PIN_8
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // NOT USED
_BV(0), // PIN_14
_BV(1), // PIN_15
_BV(3) // PIN_16
};
要设置引脚模式,并写入到脚,我创建了以下功能:
void pin_mode(uint8_t pin, uint8_t direction) {
// defeference the pointer to the direction register
uint8_t port_dir_register = *(pin_port_dir_regs[pin]);
// get pin mask
uint8_t mask = pin_bits[pin];
// set its mode
if (direction == INPUT) {
port_dir_register &= ~mask;
} else {
port_dir_register |= mask;
}
}
void pin_write(uint8_t pin, uint8_t level) {
// defeference the pointer to the output register
uint8_t port_out_register = *(pin_port_out_regs[pin]);
// get pin mask
uint8_t mask = pin_bits[pin];
// set output
if (level == LOW) {
port_out_register &= ~mask;
} else {
port_out_register |= mask;
}
}
什么是应该发生的是,你会打电话如pin_mode(7, OUTPUT)
将引脚7设置为输出,然后pin_write(7, HIGH)
将输出设置为1(其中OUTPUT和HIGH是预定义的宏)。代码编译并成功上传到AVR,但是当我测试输出时,它不响应。我想我必须写一些内存位置,但不是对应于预期的寄存器。有没有人看到我试图做到这一点的方式有问题?
为什么你不使用gcc提供的标准文件avr?另外:如果你使用类似pin_write方法的方式为引脚写入一些初始化,则只会为prog的开始阶段浪费大量代码。所有这些都可以在编译时通过模板代码完成,而不是单独针对每个引脚进行操作。为相同的作业设置一次不是8次的ddr和端口寄存器。 – Klaus
@Klaus,你指的是什么标准文件?我没有意识到现有的代码可以做我想做的事情。 此外,我并不关心现阶段的启动优化 - 但感谢您的建议。 – Sean
这看起来很浪费宝贵的RAM和ROM空间给我。你的问题不在这里讨论。我们是noi讨论网站,它太过于自负。编辑:对不起,我有最后一句话。请提供更详细的信息。见[问]。 – Olaf