会员登录 立即注册

搜索

自动扫描 ADC0 的 32 个通道

[复制链接]
崎山小鹿 发表于 昨天 19:00 | 显示全部楼层 |阅读模式
崎山小鹿
昨天 19:00 40 2 看全部
//-----------------------------------------------------------------------------
// F32x_ADC_ScanAllChannels.c
//-----------------------------------------------------------------------------
// 示例说明:
// 本程序自动扫描 ADC0 的 32 个通道(0~31),
// 每通道读取一次 ADC 值,然后通过 UART0 打印。
// 使用单端输入(负端接地),并保证串口输出完整。
//-----------------------------------------------------------------------------


#include "c8051F320.h"   // SFR 定义
#include <stdio.h>

//-----------------------------------------------------------------------------
// 16-bit SFR 定义
//-----------------------------------------------------------------------------
sfr16 TMR2RL   = 0xca;   // Timer2 重装值
sfr16 TMR2     = 0xcc;   // Timer2 计数器
sfr16 ADC0     = 0xbd;   // ADC0 数据寄存器

//-----------------------------------------------------------------------------
// 全局常量
//-----------------------------------------------------------------------------
#define SYSCLK    12000000   // 系统时钟 12MHz
#define BAUDRATE  115200     // UART 波特率

sbit LED = P2^2;            // LED 输出

#define NUM_CHANNELS (sizeof(valid_channels)/sizeof(valid_channels[0]))

unsigned char valid_channels[] = {
    0x04, // P0.4
    0x0C, // P1.4
    0x10, // P2.0
    0x11, // P2.1
    0x12, // P2.2
    0x13, // P2.3
    0x14  // P2.4(重点)
};

//-----------------------------------------------------------------------------
// 函数原型
//-----------------------------------------------------------------------------
void SYSCLK_Init(void);
void PORT_Init(void);
void ADC0_Init(void);
void UART0_Init(void);
void delay_ms(unsigned int ms); // 简单延时函数

// 读取 ADC0 值,保证 10 位有效值
unsigned int Read_ADC(void)
{
    unsigned int val;
    AD0BUSY = 1;           // 启动 ADC 转换
    while(!AD0INT);        // 等待转换完成
    AD0INT = 0;            // 清 ADC 完成标志
    val = ((ADC0H << 2) | (ADC0L >> 6)) & 0x03FF; // 右对齐 10 位
        val = ((unsigned int)ADC0H << 8) | ADC0L;
        val >>= 6;
    return val;
}

//-----------------------------------------------------------------------------
// MAIN 函数
//-----------------------------------------------------------------------------
void main(void)
{

    PCA0MD &= ~0x40;  // 关闭看门狗

    SYSCLK_Init();    // 系统时钟初始化
    PORT_Init();      // 端口初始化
    UART0_Init();     // UART 初始化
    ADC0_Init();      // ADC 初始化

    //EA = 1;           // 全局中断使能

    printf("ADC 扫描程序启动...\n");

    // 无限循环扫描 ADC 通道
    while(1)
        {
            unsigned char i;
                unsigned char ch;
                unsigned int val;
               
                for(i = 0; i < NUM_CHANNELS; i++)
                {
                    ch = valid_channels[i];   // ? 从数组取通道
               
                    AMX0P = ch;
               
                    Read_ADC();        // 丢弃第一次(MUX稳定)
                    val = Read_ADC();  // 取有效值
               
                    if(val < 20)
                        {
                            printf("CH=0x%02X, ADC=%04u (接近GND)\n", (unsigned int)ch, val);
                        }
                        else if(val > 1000)
                        {
                            printf("CH=0x%02X, ADC=%04u (接近VREF)\n", (unsigned int)ch, val);
                        }
                        else
                        {
                            printf("CH=0x%02X, ADC=%04u (有信号)\n", (unsigned int)ch, val);
                        }
                                    
               
                    delay_ms(2);
                }
       
            printf("------------------\n");
        }
  
}

//-----------------------------------------------------------------------------
// 系统时钟初始化
//-----------------------------------------------------------------------------
void SYSCLK_Init(void)
{
    OSCICN = 0x83; // 内部 12MHz 振荡器
    RSTSRC = 0x04; // 启用缺钟复位
}

//-----------------------------------------------------------------------------
// 端口初始化
//-----------------------------------------------------------------------------
void PORT_Init(void)
{
    XBR0 = 0x01;      // UART0 使能
    XBR1 = 0x40;      // 交叉开关使能,弱上拉
    P0MDOUT |= 0x10;  // TX push-pull
    P2MDOUT |= 0x04;  // LED push-pull
        //P0MDIN &= ~(1<<4); // P0.4
        P1MDIN &= ~(1<<4); // P1.4
    //P2MDIN &= ~0x10;  // P2.4 作为模拟输入
        P2MDIN &= ~0x1F;   // P2.0~P2.4 全部设为模拟输入
}



//-----------------------------------------------------------------------------
// ADC0 初始化
//-----------------------------------------------------------------------------
void ADC0_Init(void)
{
    ADC0CN = 0x80;                  // ADC 禁用,普通跟踪模式,TMR2 触发
    REF0CN = 0x03;                  // 启用内部 VREF
    AMX0P = 0x0C;                   // 初始通道 P2.4
    AMX0N = 0x1F;                   // 负端接地
    ADC0CF = ((SYSCLK/3000000)-1)<<3; // SAR 时钟 3MHz
    ADC0CF |= 0x00;                 // 右对齐结果
    //EIE1 |= 0x08;                   // 允许 ADC 完成中断
    AD0EN = 1;                       // 启用 ADC
}

//-----------------------------------------------------------------------------
// UART0 初始化
//-----------------------------------------------------------------------------
void UART0_Init(void)
{
    SCON0 = 0x10; // 8-bit 可变速率, RX 使能
    if(SYSCLK/BAUDRATE/2/256 < 1) {
        TH1 = -(SYSCLK/BAUDRATE/2);
        CKCON |= 0x08;
    } else if(SYSCLK/BAUDRATE/2/256 < 4) {
        TH1 = -(SYSCLK/BAUDRATE/2/4);
        CKCON &= ~0x0B;
        CKCON |= 0x01;
    } else if(SYSCLK/BAUDRATE/2/256 < 12) {
        TH1 = -(SYSCLK/BAUDRATE/2/12);
        CKCON &= ~0x0B;
    } else if(SYSCLK/BAUDRATE/2/256 < 48) {
        TH1 = -(SYSCLK/BAUDRATE/2/48);
        CKCON &= ~0x0B;
        CKCON |= 0x02;
    } else {
        while(1); // 不支持波特率
    }

    TL1 = TH1;
    TMOD &= ~0xF0;
    TMOD |= 0x20; // Timer1 8-bit 自动重装
    TR1 = 1;       // 启动 Timer1
    TI0 = 1;       // TX0 ready
}

//-----------------------------------------------------------------------------
// 简单延时函数
//-----------------------------------------------------------------------------
void delay_ms(unsigned int ms)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
        for(j=0;j<120;j++);
}

//-----------------------------------------------------------------------------
// End of File
//-----------------------------------------------------------------------------
天不生墨翟,万古如长夜!以墨运商,以商助墨。金双石科技长期招聘科技研发人才!微信:qishanxiaolu   电话:15876572365   公司:深圳市金双石科技有限公司
回复

使用道具 举报

 楼主| 崎山小鹿 发表于 昨天 19:08 | 显示全部楼层
崎山小鹿
昨天 19:08 看全部
这个 ADC0 是 16 位寄存器,但 ADC 实际是 10 位,右对齐后应该读取低 10 位 (ADC0L + ADC0H)。如果直接用 ADC0 读取,可能会得到 错误值(尤其是当编译器按 16 位读取时,高字节未清零,会出现 65280 之类的数)。
天不生墨翟,万古如长夜!以墨运商,以商助墨。金双石科技长期招聘科技研发人才!微信:qishanxiaolu   电话:15876572365   公司:深圳市金双石科技有限公司
回复

使用道具 举报

 楼主| 崎山小鹿 发表于 昨天 21:09 | 显示全部楼层
崎山小鹿
昨天 21:09 看全部
CH=0X04,ADC=0000(接近GND)
CH=0X0c,ADC=0015(接近GND)
CH=0X10,ADC=0015(接近GND)
CH=0X11,ADC=0010(接近GND)
CH=0X12,ADC=0002(接近GND)
CH=0X13,ADC=0001(接近GND)
CH=0X14,ADC=0000(接近GND)

引脚还是数字输入模式!这会导致:ADC输入被数字电路干扰,数值偏低,正确做法
P2MDIN &= ~0x1F;   // P2.0~P2.4 全部设为模拟输入
P0MDIN &= ~(1<<4); // P0.4
P1MDIN &= ~(1<<4); // P1.4

可以用示波器或函数信号源给 ADC 脚输入正弦波 / 方波 / 直流
观察 ADC 输出是否跟随变化
天不生墨翟,万古如长夜!以墨运商,以商助墨。金双石科技长期招聘科技研发人才!微信:qishanxiaolu   电话:15876572365   公司:深圳市金双石科技有限公司
回复

使用道具 举报

  • 您可能感兴趣
您需要登录后才可以回帖 登录 | 立即注册 |

本版积分规则 返回列表

管理员给TA私信
以墨运商,以商助墨。

查看:40 | 回复:2

  • 高端神经反馈脑波检测系统

    高端神经反馈脑波检测系统分为脑波检测、脑波分析、脑波解码三个部分。 前端主程序

    阅读:14|2026-01-06
  • 国内第三方量化平台有哪些有什么特点

    好的,我们来详细了解一下国内主流的第三方量化平台。这些平台极大地降低了个人投资者

    阅读:1679|2025-12-09
  • 为什么脑波要去除伪迹

    1. 伪迹不是大脑信号 EEG设备记录的是头皮上非常微弱的电位变化(微伏级别,μV)。

    阅读:14|2025-12-05
  • 便携可视化语音AI耳机

    项目起源: 初先生的聊天记录: 你那边掌握的技术,有办法做一个有摄像头的,墨者机

    阅读:625|2025-12-01
  • 脑波峰值频率

    看看1-30Hz脑波功率曲线 发现15Hz之后的波动很小。 去掉15Hz之后的曲线 发现4Hz

    阅读:103|2025-11-28
  • 什么是基础节律

    🧠 一、什么是“基础节律”(Basic Rhythm) 基础节律 = 在闭眼静息状态下,大脑自发

    阅读:119|2025-11-27
  • 情绪指数EQ是什么?

    情绪指数 EQ 在脑波科学(特别是情绪解码、神经反馈、BCI 领域)中,通常不是单个固定

    阅读:232|2025-11-22
  • 抗癫痫作用的SMR波

    SMR 波(Sensorimotor Rhythm)是脑电学里一个非常重要、但经常被忽略的节律。它与运

    阅读:687|2025-11-22
  • 为什么科学家认为β波与人的注意、紧张相关

    科学家之所以非常确定 β波(13–30 Hz)与“注意、警觉、紧张、执行任务”相关,不是

    阅读:727|2025-11-22
  • 为什么说θ波与冥想、困倦相关

    科学界之所以认为 θ波(Theta, 4–7 Hz)与“冥想、困倦、催眠状态”有关,并不是玄

    阅读:703|2025-11-22
金双石科技,软件开发20年,技术行业领先,您的满意,就是我们的目标,认真负责,开拓进取,让成品物超所值
关于我们
公司简介
发展历程
联系我们
本站站务
友情链接
新手指南
内容审核
商家合作
广告合作
商家入驻
新闻合作

手机APP

官方微博

官方微信

联系电话:15876572365 地址:深圳市宝安区西乡街道宝民二路宝民花园 ( 粤ICP备2021100124号-1 ) 邮箱:qishanxiaolu@qq.com
QQ|Powered by Discuz! X3.5 © 2001-2026 Discuz! Team.
快速回复 返回顶部 返回列表