我想知道程序如何与硬件设备一起使用。我想不深入地了解基础知识。
所有编程代码都具有以下内容。
我想在将程序下载到硬件时将数据存入编程存储器(ROM)。当我们运行上面所有提到的程序时,东西都进入RAM还是仅像功能数据那样进入特定区域?
当我们考虑8bit总线时,由于总线很小,如何处理超过10bit char这样的8bit数据呢?
什么是Stack,以及如何对其进行编程?
为什么void main
功能很重要?如何通过硬件识别它?
请给我有关如何使用硬件工作程序的基本概念。
答案 0 :(得分:1)
您在那里有很多问题。 首先,让我们假设一个简单的情况,例如Arduino,它是软件和硬件的组合。 软件部分开始于您编写一些简单的C ++代码,例如:
byte ledPin = 13;
void setup(){
pinMode (ledPin, OUTPUT);
}
void loop(){
digitalWrite (ledPin, HIGH);
digitalWrite (ledPin, LOW);
}
接下来,您将编译代码。 Arduino IDE(集成开发环境)在后台做了一些工作,例如添加一个main()来调用setup() 函数一次,然后loop()函数反复执行)将C ++转换为汇编代码,如下所示(不是上面的实际输出):
; Define pull-ups and set outputs high
; Define directions for port pins
ldi r16,(1<<PB7)|(1<<PB6)|(1<<PB1)|(1<<PB0)
ldi r17,(1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0)
out PORTB,r16
out DDRB,r17
; Insert nop for synchronization
nop
; Read port pins
in r16,PINB
然后,汇编器获取该代码并将其转换为十六进制格式的信息,程序员可以将该信息放入Atmega328P微控制器的ROM中。基本上,文件中的数据行,每行包含一行的开始地址,可能包含16个字节的数据,以及一个校验和,以确保在处理数据时不会损坏数据:
000100005673495a6b4f5e205673495a6b4f5e24465
这不是真实数据。 0001000可能是ROM中的起始地址,后32个字符是要编程的数据的16个字节,后4个字符是通过某种方式处理数据而创建的校验和。程序员接收数据,执行相同的操作,如果校验和正确,则会将其刻录到内存中。
可以通过两种方式将十六进制代码放入ROM中-程序员可以控制芯片并将代码直接放入内存,并且在重置后芯片将只运行代码;或者可以使用Bootloader复位后从芯片上的ROM区域运行,它将通过串行线(Rx,Tx)与PC进行通信以接收数据,然后将其写入ROM的不同区域。如果引导加载代码没有检测到PC试图与之对话,它将跳到该代码开始的ROM地址并从那里运行。
8位微控制器可能具有一些16位寄存器,可用于捕获ADC转换结果之类的东西,也可以将结果存储为两个8位字节,分别包含高低数据。
堆栈可能是专用的硬件寄存器,也可能是SRAM的一部分,用于保存诸如数学运算结果之类的内容。该代码负责将内容放到堆栈上并读回,通常不会进行编程。对于'328P,有2048个字节的SRAM,因此您只需确保没有在代码中声明过多的变量(例如字节ledPin = 13;),这些变量就用光了并且没有留出空间代码。例如,通常在328P中,这是由于尝试访问超出其限制的数组而引起的,因此,它要么返回无意义的结果,要么在超出数组末尾的写入操作覆盖其他内容时使程序崩溃。 C ++的灵活性很好,但是如果不加注意的话,也会使您陷入麻烦。
答案 1 :(得分:0)
正如@nos所说,需要大量书籍来解释它。
您在代码和硬件之间缺少的是编译器。它的作用是将您的代码(C,C ++或任何其他语言)翻译为汇编语言。汇编大约是CPU或微控制器可以理解的非常低级别的一组指令。
将程序转换为汇编后,将其上载到内存。根据架构的不同,它会进入通用存储器(冯·诺伊曼)或程序存储器(与哈佛体系结构的数据存储器相对)。
在谈论堆栈时,您也有指针。指针指向(是的,指向,真是太棒了)堆栈的“级别”。例如,您具有指向当前指令的“当前”指针。当前指令完成后,指针将递增,因此指向下一级。 调用子函数时,将使用另一个指针,该指针指向停止父函数的级别。子功能之一完成后,您返回到停止的地方。
那些指针存储在寄存器中,而寄存器是芯片中很少(且快速)的存储器。
对于主要功能,硬件在编译时不会立即识别它。对于硬件,只有一个要执行的程序(即主程序)可以调用子功能(即主程序中使用的功能)。
所以..当您编写一些代码时,用C:
int main ()
{
int a = 0;
printf("a = %d", a);
return 0;
}
main的内容被翻译成汇编,并且是您的“常规”程序。首先,将0放入寄存器的单元中。然后,将其搁置以执行printf(它使用我们保存0的单元格中的值)并将其停止在指针中的位置保存。完成后,当前指针将取回我们保存的指针的值并继续。
关于ram中的内容:您具有不同级别的内存。磁盘,硬或固态,速度慢,但又大又便宜。 Ram,更快,但更实用,更小。内置在CPU中的缓存非常快速,更小,更昂贵。寄存器也内置,速度更快但更小。当CPU使用变量时,它将进入寄存器。但是现代的CPU会“猜测”(aka prefetch)在不久的将来可能需要什么变量(例如,您读取表的前两个单元格,可能会在询问前加载第三个单元格),并将其放入高速缓存中。否则,它在ram中。
希望有所帮助,可能会有一些捷径或不正确的地方,但这大致就是它的工作方式。同样,很难在几行中总结一百页。