最新嵌入式技术基础与实践-学习(学号32106200033),2024年最新开源至上

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

//(0)数据段与代码段的定义
//(0.1)定义数据存储data段开始,实际数据存储在RAM中
.section .data
//(0.1.1)定义需要输出的字符串,标号即为字符串首地址,\0为字符串结束标志
hello_information: //字符串标号
.ascii “广州大学\n”
.ascii “32106200033\n sumresult地址和结果:\n\0”

data_format:
.ascii “%d\n\0” //printf使用的数据格式控制符

data_format1:
.ascii “%08x:%02x\n\0” //printf使用的数据格式控制符,其中8表示输出位数,
//0表示将输出的前面补上0,直到占满指定列宽为止
light_show1:
.ascii “LIGHT_BLUE:ON–\n\0” //灯亮状态提示
light_show2:
.ascii “LIGHT_BLUE:OFF–\n\0” //灯暗状态提示
light_show3:
.ascii “闪烁次数mLightCount=\0” //闪烁次数提示
//(0.1.2)定义变量
.align 4 //.word格式四字节对齐
mMainLoopCount: //定义主循环次数变量
.word 0
mFlag: //定义灯的状态标志,1为亮,0为暗
.byte ‘A’
.align 4
mLightCount:
.word 0

// 定义sumresult
sumresult:
.word 0

//(0.2)定义代码存储text段开始,实际代码存储在Flash中
.section .text
.syntax unified //指示下方指令为ARM和thumb通用格式
.thumb //Thumb指令集
.type main function //声明main为函数类型
.global main //将main定义成全局函数,便于芯片初始化之后调用
.align 2 //指令和数据采用2字节对齐,兼容Thumb指令集

//--------------------------------------------------------------------
//main.c使用的内部函数声明处

//--------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
main:
//(1)启动部分(开头)主循环前的初始化工作================
//(1.1)声明main函数使用的局部变量

//(1.2)【不变】关总中断
cpsid i
//(1.3)给主函数使用的局部变量赋初值

//(1.4)给全局变量赋初值

//(1.5)用户外设模块初始化
// 初始化蓝灯, r0、r1、r2是gpio_init的入口参数
ldr r0,=LIGHT_BLUE //r0指明端口和引脚(用=,因常量>=256,需用ldr)
mov r1,#GPIO_OUTPUT //r1指明引脚方向为输出
mov r2,#LIGHT_OFF //r2指明引脚的初始状态为亮
bl gpio_init //调用gpio初始化函数
// 初始化串口UART_User1
mov r0,#UART_User //串口号
ldr r1,=UART_BAUD //波特率
bl uart_init //调用uart初始化函数
//(1.6)使能模块中断
mov r0,#UART_User //串口号
bl uart_enable_re_int //调用uart中断使能函数

//(1.7)【不变】开总中断
cpsie i
//显示hello_information定义的字符串
ldr r0,=hello_information //待显示字符串首地址
bl printf //调用printf显示字符串

// 循环计数器R1为10	
MOV R2, #0      
MOV R0, #10	 

P1: // 标记
// r2=r0+r2
ADD R2,R2, R0
// r0–
SUB R0,R0, #1
// 如果R1大于0,则跳转回P1继续循环
CMP R0, #0
BNE P1
// 将sumresult的地址加载到R1
MOV R1, #sumresult
// 存到sumresult
STR R2, [R1]
// 输出格式
ldr R0,=data_format1 // R1 : R2
// MOV R1 ,#1
ldr R1,= #sumresult
// 输出1+2+…+10的结果
bl printf

bl .   //在此打桩(.表示当前地址),理解发光二极管为何亮起来了?

//(1)启动部分(结尾)=================================

//(2)主循环部分(开头)===============================
main_loop: //主循环标签(开头)
//(2.1)主循环次数变量mMainLoopCount+1
ldr r2,=mMainLoopCount //r2←mMainLoopCount的地址
ldr r1, [r2]
add r1,#1
str r1,[r2]
//(2.2)未达到主循环次数设定值,继续循环
ldr r2,=MainLoopNUM
cmp r1,r2
blO main_loop //未达到,继续循环
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理

//测试代码部分[理解机器码存储]
Label:
MOV R0,#0xDE //立即数范围为0x00~0xFF

ldr r0,=data_format1        //输出格式送r0 
ldr r1,=Label               //r1中是Label地址
ldrb r2,[r1]                //r2中是Label地址中的数据
bl  printf	


ldr r0,=data_format1         //输出格式送r0 
ldr r1,=Label+1              //r1中是Label+1地址
ldrb r2,[r1]                 //r2中是Label+1地址中的数据
bl  printf	

ldr r0,=data_format1         //输出格式送r0 
ldr r1,=Label+2              //r1中是Label+2地址
ldrb r2,[r1]                 //r2中是Label+2地址中的数据
bl  printf	

ldr r0,=data_format1         //输出格式送r0 
ldr r1,=Label+3              //r1中是Label+3地址
ldrb r2,[r1]                 //r2中是Label+3地址中的数据
bl  printf	

//(2.3.1)清除循环次数变量
ldr r2,=mMainLoopCount //r2←mMainLoopCount的地址
mov r1,#0
str r1,[r2]
//(2.3.2)如灯状态标志mFlag为’L’,灯的闪烁次数+1并显示,改变灯状态及标志
//判断灯的状态标志
ldr r2,=mFlag
ldr r6,[r2]
cmp r6,#‘L’
bne main_light_off //mFlag不等于’L’转
//mFlag等于’L’情况
ldr r3,=mLightCount //灯的闪烁次数mLightCount+1
ldr r1,[r3]
add r1,#1
str r1,[r3]
ldr r0,=light_show3 //显示“灯的闪烁次数mLightCount=”
bl printf
ldr r0,=data_format //显示灯的闪烁次数值
ldr r2,=mLightCount
ldr r1,[r2]
bl printf
ldr r2,=mFlag //灯的状态标志改为’A’
mov r7,#‘A’
str r7,[r2]
ldr r0,=LIGHT_BLUE //亮灯
ldr r1,=LIGHT_ON
bl gpio_set
ldr r0, =light_show1 //显示灯亮提示
bl printf
//mFlag等于’L’情况处理完毕,转
b main_exit
//(2.3.3)如灯状态标志mFlag为’A’,改变灯状态及标志
main_light_off:
ldr r2,=mFlag //灯的状态标志改为’L’
mov r7,#‘L’
str r7,[r2]
ldr r0,=LIGHT_BLUE //暗灯
ldr r1,=LIGHT_OFF
bl gpio_set
ldr r0, =light_show2 //显示灯暗提示
bl printf
main_exit:
b main_loop //继续循环
//(2)主循环部分(结尾)===============================
.end //整个程序结束标志(结尾)


### 结果


![](https://img-blog.csdnimg.cn/direct/4942455e76804eaea229bc44c5420c97.png)


## 第三章作业


### 给出所用MCU芯片型号标识所获得的信息。


(对照命名格式)


**举例:型号标识**:ATMEGA328P-AU


1. **制造商代码(Manufacturer Code)**:`AT`  这通常是制造商的缩写。在这个例子中,`AT`可能代表Atmel(现为Microchip Technology的一部分),一家知名的微控制器和微处理器制造商。
2. **系列或产品家族(Series/Family)**:`MEGA`   这表示MCU属于特定的产品系列或家族。对于Atmel来说,`MEGA`系列通常指的是基于AVR架构的高性能微控制器。
3. **型号(Model)**:`328` - 这个数字标识了MCU的具体型号。在这个例子中,它可能表示这是一款具有特定内存大小、处理能力或其他特性的微控制器。
4. **封装类型(Package Type)**:`P`  这个字母表示MCU的封装类型。`P`可能代表某种特定的封装,如PDIP(Platinum Dual In-line Package)或其他封装形式。
5. **版本或修订(Version/Revision)**:`-A`  这个后缀可能表示MCU的版本或修订级别。`A`可能意味着这是原始设计之后的某个改进版本,可能包括修正、性能提升或新特性的添加。
6. **额外信息(Additional Information)**:在这个例子中,型号标识中没有提供额外的信息,但有时制造商会添加额外的字母或数字来指示温度范围、RoHS合规性、引脚数量等。



### 给出所用MCU芯片的RAM及Flash大小、地址范围。


ATMEGA328P-AU的MCU为例:


1. **RAM(随机存取存储器)**


	* **大小**:ATMEGA328P通常有2KB的RAM。这提供了足够的工作内存来存储变量和临时数据。
	* **地址范围**:RAM的地址范围通常是从0x0000到0x07FF。2KB的地址空间
2. **Flash Memory(闪存)**


	* **大小**:ATMEGA328P通常配备有32KB的闪存。这意味着它有足够的存储空间来存储程序代码和常量数据。
	* **地址范围**:闪存的地址范围通常是从0x0000到0x7FFF。这是32KB的地址空间,每个字节都有一个唯一的地址。


## 第四章作业


### 1.学习CH04示例程序,包括gpio.c和4个工程中的main.c. 2.给出 gpio\_set(LIGHT\_RED,LIGHT\_OFF); 语句中,LIGHT RED和LIGHT OFF的值是多少?贴出每一步的查找截图。


 GPIO-BlueLight\_20230328工程


![](https://img-blog.csdnimg.cn/direct/de9f0816593f461a8f969f0de89052b1.png)


![](https://img-blog.csdnimg.cn/direct/4bc2477a75ca4255b5290bc3bd2da26b.png)


![](https://img-blog.csdnimg.cn/direct/3d60c4efa8c641beb0fdb2562b014ee6.png)


![](https://img-blog.csdnimg.cn/direct/20483ac509a141a4b751d5ec41e3e154.png)


GPIO-Output-Component\_STM32L431\_20200928工程


![](https://img-blog.csdnimg.cn/direct/ad9b1043f7e8473abfebb5e8824f548a.png)


###  3.用直接地址编程方式,实现红绿蓝三灯轮流闪烁


修改代码:


![](https://img-blog.csdnimg.cn/direct/377fa20276c24fe5a0a79c6e7510bb42.png)


完整代码:



//====================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:2017.08, 2020.05
//功能描述:见本工程的<01_Doc>文件夹下Readme.txt文件
//====================================================================

#define GLOBLE_VAR
#include “includes.h” //包含总头文件

//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处

//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程见书稿)
int main(void)
{
//(1)启动部分(开头)====================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环使用的记录主循环次数变量
uint8_t mFlag; //主循环使用的临时变量

//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;


//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount = 0;     //主循环使用的记录主循环次数变量
mFlag='B';              //主循环使用的临时变量:蓝灯状态标志


//(1.4)给全局变量赋初值

//(1.5)用户外设模块初始化
// B口9脚(蓝灯,低电平点亮)
//(1.5.1)声明变量
volatile uint32_t* RCC_AHB2;    //GPIO的B口时钟使能寄存器地址
volatile uint32_t* gpio_ptr;    //GPIO的B口基地址
volatile uint32_t* gpio_mode;   //引脚模式寄存器地址=口基地址
volatile uint32_t* gpio_bsrr;   //置位/复位寄存器地址
volatile uint32_t* gpio_brr;    //GPIO位复位寄存器
//(1.5.2)变量赋值
RCC_AHB2=(uint32_t*)0x4002104C;   //GPIO的B口时钟使能寄存器地址
gpio_ptr=(uint32_t*)0x48000400;   //GPIO的B口基地址
gpio_mode=gpio_ptr;    //引脚模式寄存器地址=口基地址
gpio_bsrr=gpio_ptr+6;  //置位/复位寄存器地址
gpio_brr=gpio_ptr+10;  //GPIO位复位寄存器
//(1.5.3)GPIO初始化
//(1.5.3.1)使能相应GPIOB的时钟
*RCC_AHB2|=(1<<1);       //GPIOB的B口时钟使能
//(1.5.3.1)定义B口9脚为输出引脚(令D19、D18=01)方法如下:
*gpio_mode &= ~(3<<18);  //0b11111111111100111111111111111111; 
*gpio_mode |=(1<<18);    //0b00000000000001000000000000000000;
//(思考:为什么这样赋值?答案见本文件末尾注①)

//(1.6)使能模块中断

//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;

printf("-----------------------------------------------------\r\n"); 
printf("金葫芦提示:直接地址方式进行GPIO输出\r\n"); 
printf("    这个编程有点难以看懂,使用构件编程就简单多了,\r\n");
printf("    但是构件制作要经过这一关,因此,我们把构件制作与\r\n");
printf("    基于构件的编程分成不同过程。学习嵌入式系统,\r\n");
printf("    以理解GPIO、UART、定时器、Flash、ADC、...\r\n");
printf("    知识要素为出发点,学会正确运用构件进行应用编程,\r\n");
printf("    理解和掌握2~3个简单构件的制作方法即可。\r\n");
printf("----------------------------------------------------\r\n"); 

//for(;;) {  }     //在此打桩,理解蓝色发光二极管为何亮起来了?

//(1)======启动部分(结尾)==========================================

//(2)======主循环部分(开头)=========================================

// gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_ON);

*gpio_bsrr|=(1<<7);     //设置灯“暗”
*gpio_bsrr|=(1<<8);     //设置灯“暗”
*gpio_bsrr|=(1<<9);     //设置灯“暗”

for(;;)     //for(;;)(开头)
{
    
    //(2.1)主循环次数+1,并判断是否小于特定常数
    mMainLoopCount++;                         //+1
    if (mMainLoopCount<=6556677)  continue;   //如果小于特定常数,继续循环
    //(2.2)主循环次数超过特定常数,灯状态进行切换(这样灯会闪烁)
    mMainLoopCount=0;      //清主循环次数
    //切换灯状态
    

    if (mFlag=='B')   //若灯状态标志为'B'
    {
     	*gpio_bsrr|=(1<<7);     //设置灯“暗”
		*gpio_brr|=(1<<9);     //设置灯“亮”	
    	
        printf("蓝灯:亮\r\n");   //通过调试串口输出灯的状态
        mFlag='G';              //改变状态标志

// gpio_set(LIGHT_RED,LIGHT_OFF);
// gpio_set(LIGHT_BLUE,LIGHT_ON);

    }
    
   else  if(mFlag=='G')                //否则,若灯状态标志为'G'    
    {

// gpio_set(LIGHT_RED,LIGHT_OFF);
// gpio_set(LIGHT_GREEN,LIGHT_ON);

		*gpio_bsrr|=(1<<9);     //设置灯“暗”
		*gpio_brr|=(1<<8);     //设置灯“亮”	

        printf("绿灯:亮\r\n");   //通过调试串口输出灯的状态
        mFlag='R';              //改变状态标志
    }	
   else 
    {

// gpio_set(LIGHT_GREEN,LIGHT_OFF);
// gpio_set(LIGHT_RED,LIGHT_ON);
*gpio_bsrr|=(1<<8); //设置灯“暗”
*gpio_brr|=(1<<7); //设置灯“亮”

        printf("红灯:亮\r\n");  //通过调试串口输出灯的状态
        mFlag='B';             //改变状态标志

    }
    
}     //for(;;)结尾
//(2)======主循环部分(结尾)========================================	

}

/*
注① 这样做的目的在于更改了D19、D18两位的值,而不改变其他位的值,不这样的话,
可能把不需要改变的位也改变了!
*/
//以下为主函数调用的子函数存放处===============================

//以下为主函数调用的子函数=====================================

//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/


结果


![](https://img-blog.csdnimg.cn/direct/6272b913879747c6ada1910f55fd3f3b.jpeg)


![](https://img-blog.csdnimg.cn/direct/cc95b38b67264b6c865a81060ff34c1d.jpeg)


###  4.用调用构件方式,实现红绿蓝的八种组合轮流闪烁


结果:


![](https://img-blog.csdnimg.cn/direct/33d329ecee504ff5bc3e2db42984b873.png)


![](https://img-blog.csdnimg.cn/direct/d09122cde6c64ff7ac59ad22111b4b9a.png)


![](https://img-blog.csdnimg.cn/direct/d348aafb65f04106a921fe9f1a13a276.jpeg)


![](https://img-blog.csdnimg.cn/direct/07e43b7a227d4d839e99e27c58504f68.jpeg)


![](https://img-blog.csdnimg.cn/direct/b863cc493ecf4298a1fc9d3ad342a94c.jpeg)


![](https://img-blog.csdnimg.cn/direct/c88aaa4d191e4908b12d712808e189f5.jpeg)


![](https://img-blog.csdnimg.cn/direct/b232fd44ba2340b6b5fafaf59c095ff9.jpeg)


![](https://img-blog.csdnimg.cn/direct/d143b662684247f4a28272b4411ec850.jpeg)


![](https://img-blog.csdnimg.cn/direct/080b2eefd2e548ab8ba02c5afa118fb0.jpeg)


完整代码



//======================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:20191108-20200419
//功能描述:见本工程的…\01_Doc\Readme.txt
//移植规则:【固定】
//======================================================================
#define GLOBLE_VAR
#include “includes.h” //包含总头文件

//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处

//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
//(1)启动部分(开头)====================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环次数变量
uint8_t mFlag; //灯的状态标志
uint32_t mLightCount; //灯的状态切换次数

//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;

//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount=0; //主循环次数变量
mFlag=‘B’; //灯的状态标志
mLightCount=0; //灯的闪烁次数

//(1.4)给全局变量赋初值

//(1.5)用户外设模块初始化
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON); //初始化红灯

//(1.6)使能模块中断

//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;

printf("------------------------------------------------------\n");   
printf("金葫芦提示:构件法输出控制小灯亮暗   \n");
printf("    第一次用构件方法点亮的蓝色发光二极管,\n");
printf("    这是进行应用编程的第一步,可以在此基础上,\n");
printf("   “照葫芦画瓢”地继续学习实践。\n");
printf("    例如:改为绿灯;调整闪烁频率等。\n");
printf("------------------------------------------------------\n"); 

//asm ("bl .");

//for(;;) {  }     //在此打桩,理解蓝色发光二极管为何亮起来了?

//(1)启动部分(结尾)====================================

//(2)主循环部分(开头)==================================

gpio_set(LIGHT_GREEN,LIGHT_OFF);  //灯“暗”
gpio_set(LIGHT_BLUE,LIGHT_OFF);  //灯“暗”
gpio_set(LIGHT_RED,LIGHT_OFF);  //灯“暗”
for(;;)   //for(;;)(开头)
{

//(2.1)主循环次数变量+1
mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
if (mMainLoopCount<=12888999) continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
mMainLoopCount=0;
//(2.3.2)如灯状态标志mFlag为’R’,灯的闪烁次数+1并显示,改变灯状态及标志
// 红色
if (mFlag==‘R’) //判断灯的状态标志
{
mLightCount++;
printf(“灯的闪烁次数 mLightCount = %d\n”,mLightCount);
mFlag=‘G’; //灯的状态标志
gpio_set(LIGHT_RED,LIGHT_ON); //灯“亮”
printf(“标志为R LIGHT_RED=%d ,LIGHT_ON = %d\n”,LIGHT_RED,LIGHT_ON);
printf(" 红灯:ON–\n\n"); //串口输出灯的状态
}
//(2.3.3)如灯状态标志mFlag为’G’,改变灯状态及标志
// 绿色
else if (mFlag==‘G’) //判断灯的状态标志
{
mLightCount++;
printf(“灯的闪烁次数 mLightCount = %d\n”,mLightCount);
mFlag=‘B’; //灯的状态标志
gpio_set(LIGHT_RED,LIGHT_OFF); //灯“暗”
gpio_set(LIGHT_GREEN,LIGHT_ON); //灯“亮”

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

	// 绿色
	else if (mFlag=='G')                    //判断灯的状态标志
	{
		mLightCount++;  
		printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
		mFlag='B';                       //灯的状态标志
		gpio_set(LIGHT_RED,LIGHT_OFF);  //灯“暗”
		gpio_set(LIGHT_GREEN,LIGHT_ON);  //灯“亮”

[外链图片转存中…(img-i84UIvZm-1715821562479)]
[外链图片转存中…(img-CAe8Diyy-1715821562479)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值