嵌入式技术基础与实践-学习(学号32106200033)

img
img

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

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

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

  • 中文名:通用输入/输出
  • 英语缩写:GPIO
  • 英语全称:General Purpose Input/Output

2.模数转换ADC与数模转换DAC

  • 中文名:模数转换
  • 英语缩写:ADC
  • 英语全称:Analog-to-Digital Converter
  • 中文名:数字模拟转换
  • 英语缩写:DAC
  • 英语全称:Digital-to-Analog Converter

3.脉冲宽度调制器PWM

  • 中文名:脉冲宽度调制
  • 英语缩写:PWM
  • 英语全称:Pulse Width Modulation

4.看门狗

  • 中文名:看门狗
  • 英语缩写:WDT
  • 英语全称:Watchdog Timer

5.液晶显示(LCD)

  • 中文名:液晶显示
  • 英语缩写:LCD
  • 英语全称:Liquid Crystal Display

6.发光二极管(LED)

  • 中文名:发光二极管
  • 英语缩写:LED
  • 英语全称:Light Emitting Diode

7.键盘

  • 中文名:键盘
  • 英语缩写:KBD
  • 英语全称:Keyboard
与通信相关的术语

1.并行通信(同时发送多位)

  • 中文名:并行通信
  • 英语缩写:Parallel Comm.
  • 英语全称:Parallel Communication

2.串行通信UART(一位一位发送)

  • 中文名:串行通信
  • 英语缩写:UART
  • 英语全称:Universal Asynchronous Receiver

3.串行外设接口SPI

  • 中文名:串行外设接口
  • 英语缩写:SPI
  • 英语全称:Serial Peripheral Interface

4.集成电路互联总线I2C

  • 中文名:集成电路互联总线
  • 英语缩写:I2C
  • 英语全称:Inter-Integrated Circuit

5.通用串行总线USB

  • 中文名:通用串行总线
  • 英语缩写:USB
  • 英语全称:Universal Serial Bus

6.控制器局域网CAN

  • 中文名:控制器局域网
  • 英语缩写:CAN
  • 英语全称:Controller Area Network

7.边界扫描测试协议JTAG(工厂测试芯片)

  • 中文名:边界扫描测试协议
  • 英语缩写:BSTP
  • 英语全称:Boundary Scan Test Protocol

8.串行线调试技术SWD

  • 中文名:串行线调试技术
  • 英语缩写:SWD
  • 英语全称:Serial Wire Debug

运行实例:

编译、下载与运行第一个嵌入式程序

步骤一:硬件连线

步骤二:打开环境,导入工程

步骤三:编译工程

步骤四:连接GEC

步骤五:下载机器码

步骤六:观察运行结果

步骤七: 通过串口观察运行情况

第二章作业

描述:打开04-Software/ch02/CH02-1-20220118工程目录编译下载运行,理解并学习main.s汇编源文件。

写出main.s中94~101行语句的C语言描述

修改main.s源文件,增加以下内容:
1、在第一行显示“广州大学”字样。
2、编写一个1+2+…+10的程序,将求和结果存入名为“sumresult”的内存单元中,并将求和结果用printf显示出来。

结论经过测试和观察,data_format输出格式输出的是R1;  而data_format1输出格式输出的是R1 : R2,且R1适合放内存地址,R2放结果数据。

C语言描述main.s中main_loop里的语句

#include<iostream>
using namespace std;

int* mMainLoopCount = new int(1); //地址
const  int MainLoopNUM = 10; // 常数(循环结束的阻止次数)

int main() {

    int  r2 = MainLoopNUM;  
    int r1 = *mMainLoopCount; // 取数
    // 为达到主循环次数设定值,继续循环
    for (int i = r1; r1 != r2; i++) {
        r1=i;
        *mMainLoopCount = r1;
    }
    // 达到主循环次数设定值
    delete mMainLoopCount; // 释放空间

    return 0;
}

代码

内存单元命名为sumresult

编写1-10的累加程序

完整代码:

//=====================================================================
//文件名称:main.s
//功能概要:汇编编程调用GPIO构件控制小灯闪烁(利用printf输出提示信息)
//版权所有:SD-ARM(sumcu.suda.edu.cn)
//版本更新:20180810-20191018
//=====================================================================
.include "include.inc"    //头文件中主要定义了程序中需要使用到的一些常量
//(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     //整个程序结束标志(结尾)

结果

第三章作业

给出所用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工程

GPIO-Output-Component_STM32L431_20200928工程

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

修改代码:

完整代码:

//====================================================================
//文件名称: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
 */

结果

img
img

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

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

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

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


结果


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


[外链图片转存中...(img-QBa34sGr-1715803485238)]
[外链图片转存中...(img-Xq7y7fRS-1715803485238)]

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

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

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值