您的位置:首页 > 财经 > 产业 > 制作公司网站步骤_建立网站的内容规划_电商培训机构排名前十_seo短视频加密路线

制作公司网站步骤_建立网站的内容规划_电商培训机构排名前十_seo短视频加密路线

2024/10/31 11:16:46 来源:https://blog.csdn.net/m0_51830537/article/details/142849814  浏览:    关键词:制作公司网站步骤_建立网站的内容规划_电商培训机构排名前十_seo短视频加密路线
制作公司网站步骤_建立网站的内容规划_电商培训机构排名前十_seo短视频加密路线

ARM 下的 ADC(模数转换器)

  • ADC(Analog to Digital Converter,模数转换器)是嵌入式系统中非常重要的一个模块,负责将连续变化的模拟信号(如温度、电压、电流等)转换为数字信号,供 CPU 和程序进行处理。
  1. ADC 基本概念
    • 模拟量(Analog Quantity):模拟量是连续变化的物理量,比如温度、湿度、光照强度、电压等。它们的变化是连续的,无法直接被数字处理器理解。
    • 数字量(Digital Quantity):数字量是离散的、不连续的。数字处理器只能处理数字量,比如 1 和 0 的组合。
    • 转换:ADC 模块负责将模拟信号(比如电压信号)转换为相应的数字量,使处理器能够读取和处理。
  2. 工作原理
  • 在 ARM 系统中的 ADC 模块通常是一个基于电压的转换器,它通过对输入电压信号的采样,将其转换为对应的数字值。
  • 例如,在 12 位 ADC 中,输入电压的范围通常为 0 - Vref,其中 Vref 是参考电压。输入电压 Vx 可以通过以下公式转换为数字值
    B L = V x V r e f × 4095 BL = \frac{V_x}{V_{ref}} \times 4095 BL=VrefVx×4095
    • BL 是 ADC 转换得到的数字值,12 位 ADC 的最大值是 4095(即 2^12 - 1)
    • Vx 是输入的电压值
    • Vref 是参考电压,通常为 3.3V 或 5V
  1. ARM下的ADC特点
    • 分辨率:ADC 的分辨率决定了它能将模拟量细分为多少个数字值。例如,12 位分辨率的 ADC 能将输入电压分成 4096 个离散的数字量(即 0 - 4095)
    • 采样速度:这是 ADC 每秒能够执行的转换次数,通常以 Samples Per Second(SPS,样本/秒)为单位
    • 参考电压(Vref):这是 ADC 转换时的参考电压,通常由外部或者内部的电压源提
  2. ADC编程步骤
    • 配置 GPIO 引脚为模拟输入模式: 在一些 ARM Cortex-M 系列的 MCU 中,ADC 通道与特定的 GPIO 引脚绑定,在使用 ADC 之前需要将 GPIO 配置为模拟模式。
    • 配置 ADC 模块:
      • 配置分辨率和采样速度(如 12 位,1 MSPS)。
      • 设置参考电压(Vref)。
    • 启动转换: 启动 ADC 转换,等待 ADC 模块完成采样并将结果存储在数据寄存器中。
    • 读取 ADC 数据寄存器: 一旦转换完成,ADC 数据寄存器将存储转换后的数字值,可以通过访问寄存器读取这个值。
  3. ARM 典型寄存器配置(伪代码)
// 伪代码 - ARM ADC 配置与读取
//基于 ARM Cortex-M 系列的 ADC 配置步骤
void ADC_Init(void)
{// 1. 配置 GPIO 引脚为模拟输入模式GPIO_PinConfig(GPIOA, PIN1, GPIO_MODE_ANALOG);// 2. 配置 ADC 模块ADC1->CR1 = 0;               // 配置为12位模式ADC1->SQR1 = 0;              // 设置规则序列长度为 1ADC1->SMPR2 |= ADC_SMPR2_SMP10; // 设置采样时间// 3. 启动 ADCADC1->CR2 |= ADC_CR2_ADON;    // 启用 ADC 模块
}uint16_t ADC_Read(void)
{// 4. 启动转换ADC1->CR2 |= ADC_CR2_SWSTART; // 启动转换// 5. 等待转换完成while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换结束// 6. 读取 ADC 数据寄存器return ADC1->DR; // 返回转换后的值
}
  1. ARM 下的 ADC 实际应用
    • 温度测量:读取热敏电阻输出的模拟电压值,将其转换为数字值,再根据转换结果计算温度。
    • 电压监测:通过电压分压电路,监测电池或电源的电压值,进而判断电源状态。
    • 光强度检测:读取光电二极管或光敏电阻的模拟信号,转换为数字量后判断环境光照强度。

ARM的ADC编程实例(main.c)

  1. 第一步:UART初始化
    目的:初始化串口通信模块,使 CPU 可以通过 UART 向外部设备发送字符数据(例如,输出 ADC 转换得到的电压值
#define	GPA1CON  	*(volatile long*)0x11400020	// GPIO A1 控制寄存器地址
#define	ULCON2		*(volatile long*)0x13820000	// UART 控制寄存器 ULCON2,设置 UART 数据格式
#define	UCON2		*(volatile long*)0x13820004	// UART 控制寄存器 UCON2,设置 UART 的控制模式(轮询模式)
#define	UTRSTAT2	*(volatile long*)0x13820010	// UART 状态寄存器,用于查询 UART 是否就绪
#define	UTXH2		*(volatile long*)0x13820020	// UART 发送寄存器,用于向 UART 发送数据#define	UBRDIV2		*(volatile long*)0x13820028	// UART 波特率寄存器,设置波特率
#define	UFRACVAL2 	*(volatile long*)0x1382002C	// UART 波特率分数寄存器,用于波特率微调void uart_init(void)
{GPA1CON = GPA1CON & ~0xF;                  // 清除 GPA1_0 的配置位,确保后续操作正确GPA1CON = GPA1CON | (1<<1);                // 设置 GPA1_0 为 UART 发送功能GPA1CON = GPA1CON & ~(0xF<<4);             // 清除 GPA1_1 的配置位GPA1CON = GPA1CON | (1<<5);                // 设置 GPA1_1 为 UART 接收功能ULCON2 = ULCON2 | 0x3;                     // 设置 UART 数据格式为 8 位数据,无校验位,1 位停止位ULCON2 = ULCON2 & ~(1<<2);                 // 确保校验位为无校验UCON2 &= ~(3);                             // 清除 UART 控制模式位UCON2 |= 1<<0;                             // 设置 UART 为轮询接收模式UCON2 &= ~(3<<2);                          // 清除 UART 控制模式位UCON2 |= 1<<2;                             // 设置 UART 为轮询发送模式UBRDIV2 = 53;                              // 设置 UART 波特率分频值UFRACVAL2 = 4;                             // 设置 UART 波特率的分数部分
}
  1. 第二步:ADC初始化
    目的:初始化 ADC,使 CPU 能够从指定的 ADC 通道读取模拟电压值,并转换为数字信号
#define	ADCCON  *(volatile long*)0x126C0000    // ADC 控制寄存器地址
#define	ADCDAT	*(volatile long*)0x126C000C    // ADC 数据寄存器地址
#define	ADCMUX	*(volatile long*)0x126C001C	// ADC 多路复用器寄存器地址,选择 ADC 输入通道void adc_init(void)
{ADCCON |= 1<<16;                           // 启用 12 位分辨率ADCCON |= 1<<14;                           // 使能分频器ADCCON &= ~(0xFF<<6);                      // 清除原有的分频器设置ADCCON |= 19<<6;                           // 设置分频器值为 19ADCCON &= ~(1<<2);                         // 禁用空闲模式ADCCON |= 1<<1;                            // 启用自动重新转换ADCCON |= 1<<0;                            // 启动 ADC 转换ADCMUX = 3;                                // 选择 ADC 输入通道 3int reg = ADCDAT;                          // 读取一次 ADC 数据寄存器,准备初始化
}
  1. 第三步:获取 ADC 数据并将其转换为电压值
    目的:通过 ADC 读取输入电压并转换为数字值(mV),用于后续的显示。
int adc_get_mv(void)
{int reg = ADCDAT & 0xFFF;                  // 获取 ADC 数据寄存器中的 12 位有效数据int mv = reg * 1800 / 4095;                // 将 ADC 数据转换为毫伏(1800mV 为参考电压)return mv;                                 // 返回计算出的电压值
}
  1. 第四步:通过 UART 输出电压值
    目的:将 ADC 读取的电压值以字符形式通过 UART 发送,显示到外部设备。
void main(void)
{int mv;int qian, bai, shi, ge;uart_init();                               // 初始化 UART,配置波特率和 GPIOadc_init();                                // 初始化 ADC,设置分频器和输入通道while(1){mv = adc_get_mv();                     // 获取 ADC 转换得到的电压值(以 mV 为单位)// 分离电压值的每一位数字(千、百、十、个位)qian = mv / 1000;                      // 计算千位putc(qian + '0');                      // 发送千位数字bai = mv / 100 % 10;                   // 计算百位putc(bai + '0');                       // 发送百位数字shi = mv / 10 % 10;                    // 计算十位putc(shi + '0');                       // 发送十位数字ge = mv % 10;                          // 计算个位putc(ge + '0');                        // 发送个位数字// 发送 'mv' 后缀,表示毫伏putc('m');putc('v');putc('\r');                            // 发送回车符putc('\n');                            // 发送换行符mysleep(200);                          // 延时 200ms}
}
  1. 第五步:将电压值拆分成千、百、十、个位并输出
    目的:将电压值(以毫伏为单位)拆分成千位、百位、十位和个位,然后逐位通过 UART 输出字符形式的数值,最后附加上 “mv” 单位。
void main(void)
{int mv;int qian, bai, shi, ge;uart_init();                               // 初始化 UART,配置波特率和 GPIOadc_init();                                // 初始化 ADC,设置分频器和输入通道while(1){mv = adc_get_mv();                     // 获取 ADC 转换得到的电压值(以 mV 为单位)// 分离电压值的每一位数字(千、百、十、个位)qian = mv / 1000;                      // 计算千位putc(qian + '0');                      // 发送千位数字bai = mv / 100 % 10;                   // 计算百位putc(bai + '0');                       // 发送百位数字shi = mv / 10 % 10;                    // 计算十位putc(shi + '0');                       // 发送十位数字ge = mv % 10;                          // 计算个位putc(ge + '0');                        // 发送个位数字// 发送 'mv' 后缀,表示毫伏putc('m');                             // 发送字符 'm'putc('v');                             // 发送字符 'v'putc('\r');                            // 发送回车符 '\r'putc('\n');                            // 发送换行符 '\n'mysleep(200);                          // 延时 200 毫秒,避免过快刷新输出}
}
  1. 第六步:延时函数 mysleep
    目的:通过简单的循环实现延时功能,避免程序过快地进行下一轮 ADC 读取与数据输出
void mysleep(int ms)
{while(ms--){                               // 每次减少 1 毫秒int num = 0x1FFF/2;                    // 初始化计数器,数值决定延时时间while(num--);                          // 空循环,达到延时效果}
}
  1. 综合示例
//使用 UART 和 ADC 来获取模拟电压值并通过 UART 输出电压读数。它包括 UART 初始化、ADC 初始化、获取 ADC 数据和通过串口输出电压值的过程。
#define	GPA1CON  	*(volatile long*)0x11400020	  // GPIO A1 控制寄存器
#define	ULCON2		*(volatile long*)0x13820000	  // UART2 控制寄存器,设置数据位、停止位、校验等
#define	UCON2		*(volatile long*)0x13820004	  // UART2 控制寄存器,设置轮询、发送和接收模式
#define	UTRSTAT2	*(volatile long*)0x13820010	  // UART2 状态寄存器,检查发送和接收状态
#define	UTXH2		*(volatile long*)0x13820020	  // UART2 发送缓冲寄存器,发送数据
#define	URXH2		*(volatile long*)0x13820024	  // UART2 接收缓冲寄存器,接收数据
#define	UBRDIV2		*(volatile long*)0x13820028	  // UART2 波特率分频寄存器,设置波特率
#define	UFRACVAL2 	*(volatile long*)0x1382002C	  // UART2 波特率小数部分寄存器// 初始化 UART
void uart_init(void)
{GPA1CON = GPA1CON & ~0xF;        // 清除 GPA1_0 的原有配置GPA1CON = GPA1CON | (1<<1);      // 设置 GPA1_0 为 UART TX (发送)GPA1CON = GPA1CON & ~(0xF<<4);   // 清除 GPA1_1 的原有配置GPA1CON = GPA1CON | (1<<5);      // 设置 GPA1_1 为 UART RX (接收)ULCON2 = ULCON2 | 0x3;           // 配置 UART2:8 位数据,无校验,1 位停止位ULCON2 = ULCON2 & ~(1<<2);       // 设置 1 位停止位ULCON2 = ULCON2 & ~(7<<3);       // 禁用校验位ULCON2 = ULCON2 & ~(1<<6);       // 禁用红外模式UCON2 &= ~(3);                   // 清除发送接收的控制配置UCON2 |= 1<<0;                   // 轮询模式接收UCON2 &= ~(3<<2);                // 清除发送配置UCON2 |= 1<<2;                   // 轮询模式发送UBRDIV2 = 53;                    // 设置波特率的整数部分UFRACVAL2 = 4;                   // 设置波特率的小数部分
}// 发送单个字符
void putc(char ch)
{while(  (UTRSTAT2 & (1<<1)) == 0 ) ;   // 等待直到发送缓冲区为空UTXH2 = ch;                            // 向 UART2 发送寄存器写入字符
}// 发送字符串
void puts(char *s)
{int i = 0;while (s[i]) {            // 遍历字符串putc(s[i]);           // 逐字符发送i++;}
}#define	ADCCON  *(volatile long*)0x126C0000	 // ADC 控制寄存器
#define	ADCDAT	*(volatile long*)0x126C000C	 // ADC 数据寄存器,存放采样数据
#define	ADCMUX	*(volatile long*)0x126C001C	 // ADC 多路复用器,选择输入通道// 简单的毫秒级延时函数
void mysleep(int ms)
{while (ms--) {int num = 0x1FFF / 2;    // 简单的循环延时while (num--);}
}// 初始化 ADC
void adc_init(void)
{int reg;ADCCON |= 1<<16;             // 启用 12 比特分辨率ADCCON |= 1<<14;             // 启用分频值ADCCON &= ~(0xFF<<6);        // 清除分频值ADCCON |= 19<<6;             // 设置分频值为 19ADCCON &= ~(1<<2);           // 禁用空闲模式ADCCON |= 1<<1;              // 重新转换ADCCON |= 1<<0;              // 启动 ADC 转换ADCMUX = 3;                  // 设置 ADC 输入通道为 3reg = ADCDAT;                // 读取 ADC 数据寄存器,清除第一次转换的值
}// 获取 ADC 值并转换为毫伏值
int adc_get_mv(void)
{int reg = ADCDAT & 0xFFF;    // 获取 12 位有效的 ADC 数据int mv = reg * 1800 / 4095;  // 将 ADC 值转换为电压(1800 毫伏参考电压)return mv;
}// 主函数
void main(void)
{int mv;int qian, bai, shi, ge;       // 用于存储电压的千位、百位、十位和个位uart_init();                  // 初始化 UARTadc_init();                   // 初始化 ADCwhile (1) {mv = adc_get_mv();         // 获取电压值(例如 1658 mV)qian = mv / 1000;          // 获取千位putc(qian + '0');          // 通过 UART 发送千位数字bai = mv / 100 % 10;       // 获取百位putc(bai + '0');           // 通过 UART 发送百位数字shi = mv / 10 % 10;        // 获取十位putc(shi + '0');           // 通过 UART 发送十位数字ge = mv % 10;              // 获取个位putc(ge + '0');            // 通过 UART 发送个位数字putc('m');                 // 发送字符 'm'putc('v');                 // 发送字符 'v'putc('\r');                // 发送回车符putc('\n');                // 发送换行符mysleep(200);              // 延时 200 毫秒}return;
}
其余相关代码
  1. start.S
.global  delay1s                     @ 声明全局符号 delay1s,用于定义延时函数
.text                                @ 代码段的开始
.global _start                       @ 声明全局符号 _start,程序的入口点_start:b		reset                  @ 程序启动时跳转到 reset,执行复位后的初始化操作ldr		pc,_undefined_instruction  @ 设置未定义指令异常的处理地址ldr		pc,_software_interrupt     @ 设置软件中断异常的处理地址ldr		pc,_prefetch_abort         @ 设置预取指令异常的处理地址ldr		pc,_data_abort             @ 设置数据访问异常的处理地址ldr		pc,_not_used               @ 没有使用的异常,保留ldr		pc,_irq                    @ 设置普通中断 (IRQ) 的处理地址ldr		pc,_fiq                    @ 设置快速中断 (FIQ) 的处理地址_undefined_instruction: .word  _undefined_instruction   @ 定义未定义指令异常处理地址
_software_interrupt:	.word  _software_interrupt      @ 定义软件中断异常处理地址
_prefetch_abort:		.word  _prefetch_abort           @ 定义预取异常处理地址
_data_abort:			.word  _data_abort               @ 定义数据异常处理地址
_not_used:				.word  _not_used                 @ 保留,未使用的异常
_irq:					.word  _irq                      @ 定义 IRQ 处理地址
_fiq:					.word  _fiq                      @ 定义 FIQ 处理地址reset: ldr	r0,=0x40008000          @ 将异常向量表的起始地址设置为 0x40008000mcr	p15,0,r0,c12,c0,0       @ 将向量基地址 (VBAR) 设置为 r0(即 0x40008000)init_stack:ldr		r0,=stacktop           @ 获取栈顶指针的值到 r0 中/******** SVC 模式的栈 ********/mov		sp,r0                 @ 将栈顶指针设置为当前栈指针 (sp)sub		r0,#128*4            @ 为 IRQ 模式预留 512 字节的栈空间/**** IRQ 模式的栈 ****/msr		cpsr,#0xd2           @ 切换到 IRQ 模式mov		sp,r0                 @ 设置 IRQ 模式的栈指针sub		r0,#128*4            @ 为 FIQ 模式预留 512 字节的栈空间/*** FIQ 模式的栈 ***/msr 	cpsr,#0xd1           @ 切换到 FIQ 模式mov		sp,r0                 @ 设置 FIQ 模式的栈指针sub		r0,#0                @ FIQ 模式不需要更多的栈空间/*** Abort 模式的栈 ***/msr		cpsr,#0xd7           @ 切换到 Abort 模式mov		sp,r0                 @ 设置 Abort 模式的栈指针sub		r0,#0                @ Abort 模式不需要更多的栈空间/*** Undefined 模式的栈 ***/msr		cpsr,#0xdb           @ 切换到 Undefined 模式mov		sp,r0                 @ 设置 Undefined 模式的栈指针sub		r0,#0                @ Undefined 模式不需要更多的栈空间/*** System 和 User 模式的栈 ***/msr		cpsr,#0x10           @ 切换到 System/User 模式mov		sp,r0                 @ 设置 System/User 模式的栈指针,预留 1024 字节空间b		main                 @ 跳转到 main 函数,开始执行主程序delay1s:ldr      r4,=0x1ffffff         @ 将延时循环计数器的值装入 r4
delay1s_loop:sub    r4,r4,#1               @ 计数器减 1cmp   r4,#0                   @ 比较计数器是否归零bne    delay1s_loop           @ 如果没有归零,继续循环mov   pc,lr                   @ 如果计数结束,返回调用处.align	4                         @ 对齐到 4 字节边界,优化存储器访问/****  SWI 中断处理程序  ****/.data                              @ 数据段的开始stack:	.space  4*512                 @ 为所有模式分配 512 字节栈空间
stacktop:                           @ 栈顶符号.end                               @ 汇编文件的结束
  1. Makefile
all:arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.Sarm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.carm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o main.elfarm-none-linux-gnueabi-objcopy -O binary  main.elf main.binarm-none-linux-gnueabi-objdump -D main.elf > main.dis
clean:rm -rf *.bak start.o main.o  main.elf main.bin main.dis
  1. map.lds

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com