读取线路板上的电流和电压

*************

C++

topic: 嵌入式

*************

之前做了很多的代码题目,在LeetCode上。在嵌入式开发上,其实不需要用到很多算法,往往一些简单的代码就可以解决很多的问题。

比如,我需要读取控制板上的电流和电压,用于判断电机的运转工况,用到的芯片是上文提到的KV4x的。那么代码就很简单。接下来按照步骤进行到代码的创作。

最重要的,也是最开始的,了解芯片的ADC模块,analog digital converter,通道和配置。这个在商品文章中已经深入的学习过了。

KV4x芯片data sheet - 持续学习中-优快云博客https://blog.youkuaiyun.com/ElseWhereR/article/details/145192348?spm=1001.2014.3001.5501https://blog.youkuaiyun.com/ElseWhereR/article/details/145192348?spm=1001.2014.3001.5501

  1. 在主板上确认电流和电压接到哪些引脚,引脚对应的ADC的通道是什么 。
  2. 配置ADC模块,设置分辨率、参考电压、采样速率等单数。
  3. 配置GPIO,把连接电流和电压的引脚设置为模拟输入模式。
  4. 对于电流的测量,可能需要一个电流感应电阻,把电流转换成电压,再通过ADC读取。
  5. 电压的测量直接通过分压电阻网络,把电压降到ADC的输入范围内。
  6. 然后,写代码初始化ADC,配置相关寄存器。
  7. 写函数来读取ADC的值,转换成实际的电流和电压数值。
  8. 需要处理采样平均,滤波,提高数据的准确性。
  9. 最后,测试一下,看看读取的值是否合理,和实际测量的值对比一下。

看一下简化的代码:

#include "KV4XP100M168.h"
#include "adc.h"
#include "gpio.h"

// 配置ADC
void ADC_Init() {
    // 配置ADC时钟
    // 使能ADC模块
    // 设置参考电压
    // 设置分辨率
    // 配置ADC通道
    // 启动ADC
}

// 读取ADC值
uint16_t ADC_Read(uint8_t channel) {
    // 选择通道
    // 启动转换
    // 等待转换完成
    // 读取转换结果
    return adc_value;
}

// 主函数
int main() {
    // 初始化系统时钟
    SystemClock_Config();

    // 初始化GPIO
    GPIO_Init();

    // 初始化ADC
    ADC_Init();

    while (1) {
        // 读取电压通道的ADC值
        uint16_t voltage_adc = ADC_Read(VOLTAGE_CHANNEL);
        // 转换为实际电压值
        float voltage = voltage_adc * (V_REF / (float)(ADC_RESOLUTION - 1));

        // 读取电流通道的ADC值
        uint16_t current_adc = ADC_Read(CURRENT_CHANNEL);
        // 转换为实际电流值
        float current = (current_adc * (V_REF / (float)(ADC_RESOLUTION - 1))) / CURRENT_SHUNT_RESISTANCE;

        // 处理电压和电流数据
        // ...

        // 延时
        Delay_ms(100);
    }
}

对于配置ADC模块,简化的代码如下:

#include "KV4XP100M168.h"
#include "adc.h"
#include "gpio.h"
#include <stdint.h>

// 定义常量
#define V_REF 3.3f                  // 参考电压,假设是3.3V
#define ADC_RESOLUTION 4095         // 12位ADC
#define CURRENT_SHUNT_RESISTANCE 0.1f  // 电流检测电阻,0.1欧姆
#define VOLTAGE_CHANNEL 0           // 电压测量通道,假设是通道0
#define CURRENT_CHANNEL 1           // 电流测量通道,假设是通道1

// ADC初始化函数
void ADC_Init(void) {
    // 使能ADC0时钟
    SIM->SCGCADC |= SIM_SCGCADC_ADC0_CLK_ENABLE;

    // 选择内部参考电压
    ADC0->RGMC1 |= ADC_RGMC1_VREFEN_MASK;

    // 设置12位分辨率
    ADC0->RGMC1 &= ~ADC_RGMC1_MODE_MASK;

    // 配置GPIO引脚为模拟输入模式
    // 假设电压通道是GPIOA第0脚,电流通道是GPIOA第1脚
    GPIOA->PDDR &= ~((1 << 0) | (1 << 1));  // 确保引脚不是推挽输出
    GPIOA->GCR |= (1 << 0) | (1 << 1);      // 使能模拟功能

    // 其他配置,如采样时间、序列等
    // ...
}

// 读取ADC值的函数
uint16_t ADC_Read(uint8_t channel) {
    // 选择通道
    ADC0->RGMCTL = (ADC0->RGMCTL & ~ADC_RGMCTL_RGMCHAN_MASK) | (channel << ADC_RGMCTL_RGMCHAN_SHIFT);

    // 启动转换
    ADC0->RGMCTL |= ADC_RGMCTL_RGMSTART_MASK;

    // 等待转换完成
    while ((ADC0->RGMSTAT & ADC_RGMSTAT_RGMEOCF_MASK) == 0);

    // 读取转换结果
    uint16_t adc_value = ADC0->RGMDAT0;

    // 清除转换完成标志
    ADC0->RGMSTAT |= ADC_RGMSTAT_RGMEOCF_MASK;

    return adc_value;
}

// 延时函数
void Delay_ms(uint32_t ms) {
    for (uint32_t i = 0; i < ms; i++) {
        for (uint32_t j = 0; j < 1000; j++);
    }
}

// 主函数
int main(void) {
    // 初始化系统时钟
    SystemClock_Init();

    // 初始化ADC
    ADC_Init();

    while (1) {
        // 读取电压通道的ADC值
        uint16_t voltage_adc = ADC_Read(VOLTAGE_CHANNEL);

        // 读取电流通道的ADC值
        uint16_t current_adc = ADC_Read(CURRENT_CHANNEL);

        // 转换为实际电压和电流值
        float voltage = (voltage_adc * V_REF) / (float)ADC_RESOLUTION;
        float current = (current_adc * V_REF) / (float)(CURRENT_SHUNT_RESISTANCE * ADC_RESOLUTION);

        // 处理电压和电流数据
        // ...

        // 延时
        Delay_ms(100);
    }
}

代码其实很简单,这些代码比LeetCode上的题目简单多了,比较困难的是系统的对芯片进行设置,要结合相应的电路和系统的处理关系。代码只是工具,不能单出,代码加上系统控制,那就比较牛逼了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值