STC8 16通道模拟采集 + 4路串口 + 8路PWM 程序

简介: STC8 16通道模拟采集 + 4路串口 + 8路PWM 程序

一、系统架构设计

┌─────────────────────────────────────────────────────────────┐
│                    STC8 多功能数据采集系统                 │
├─────────────────────────────────────────────────────────────┤
│  模拟采集层  │  通信接口层  │  控制输出层  │  系统管理层   │
│              │              │              │              │
│  • 16路ADC   │  • UART1     │  • 8路PWM    │  • 系统初始化 │
│  • 采样率配置 │  • UART2     │  • 频率调节  │  • 中断管理   │
│  • 滤波处理  │  • UART3     │  • 占空比控制 │  • 看门狗     │
│  • 数据校准  │  • UART4     │  • 死区设置  │  • 低功耗模式 │
└─────────────────────────────────────────────────────────────┘

二、硬件配置

2.1 STC8A8K64S4A12 引脚分配

STC8A8K64S4A12 引脚配置:
┌─────────────┬─────────────────────┬──────────────────┐
│ 引脚        │ 功能描述            │ 说明             │
├─────────────┼─────────────────────┼──────────────────┤
│ P0.0-P0.7   │ ADC0-ADC7          │ 模拟输入通道0-7  │
│ P1.0-P1.7   │ ADC8-ADC15         │ 模拟输入通道8-15 │
│ P2.0-P2.7   │ PWM0-PWM7          │ PWM输出通道0-7   │
│ P3.0/RXD1   │ UART1接收          │ 串口1接收        │
│ P3.1/TXD1   │ UART1发送          │ 串口1发送        │
│ P3.2/RXD2   │ UART2接收          │ 串口2接收        │
│ P3.3/TXD2   │ UART2发送          │ 串口2发送        │
│ P3.4/RXD3   │ UART3接收          │ 串口3接收        │
│ P3.5/TXD3   │ UART3发送          │ 串口3发送        │
│ P3.6/RXD4   │ UART4接收          │ 串口4接收        │
│ P3.7/TXD4   │ UART4发送          │ 串口4发送        │
│ P4.0        │ ADC参考电压选择    │ 参考电压控制     │
│ P4.1        │ 系统时钟输出       │ 时钟输出         │
│ P4.2        │ 外部中断0          │ 外部触发         │
│ P4.3        │ 外部中断1          │ 外部触发         │
│ P5.0        │ 系统复位/唤醒      │ 复位引脚         │
└─────────────┴─────────────────────┴──────────────────┘

2.2 硬件连接示例

模拟输入:
• 通道0-7:P0.0-P0.7,连接传感器信号
• 通道8-15:P1.0-P1.7,连接传感器信号
• 参考电压:P4.0,连接2.5V精密参考电压

PWM输出:
• PWM0-PWM3:P2.0-P2.3,连接电机驱动/LED调光
• PWM4-PWM7:P2.4-P2.7,连接舵机/继电器

串口通信:
• UART1:连接上位机/调试终端
• UART2:连接GPS模块
• UART3:连接无线通信模块
• UART4:连接传感器扩展板

三、完整源码实现

3.1 系统头文件 (stc8_multifunc.h)

#ifndef __STC8_MULTIFUNC_H
#define __STC8_MULTIFUNC_H

#include "STC8.H"
#include <intrins.h>
#include <string.h>
#include <stdio.h>

// 系统时钟配置
#define SYSCLK          24000000    // 24MHz系统时钟
#define BAUD_RATE      115200      // 串口波特率

// 模拟采集配置
#define ADC_CHANNELS   16          // 16个ADC通道
#define ADC_SAMPLES    10          // 每个通道采样次数
#define ADC_FILTER_LEN 5           // 滤波长度

// PWM配置
#define PWM_CHANNELS   8           // 8路PWM
#define PWM_BASE_FREQ  1000        // PWM基准频率1kHz
#define PWM_RESOLUTION 1000        // PWM分辨率1000级

// 串口配置
#define UART_BUFF_SIZE 128         // 串口缓冲区大小
#define UART_TIMEOUT   100         // 串口超时时间(ms)

// 系统状态枚举
typedef enum {
   
    SYS_INIT = 0,
    SYS_RUNNING,
    SYS_SLEEP,
    SYS_FAULT
} SystemState_t;

// ADC数据结构体
typedef struct {
   
    uint16_t raw_value[ADC_CHANNELS];      // 原始ADC值
    float    voltage[ADC_CHANNELS];        // 转换后的电压值
    float    filtered[ADC_CHANNELS];       // 滤波后的值
    uint8_t  channel_enable[ADC_CHANNELS]; // 通道使能标志
    uint32_t sample_count;                 // 采样计数
} ADC_Data_t;

// PWM数据结构体
typedef struct {
   
    uint16_t frequency[PWM_CHANNELS];      // PWM频率
    uint16_t duty_cycle[PWM_CHANNELS];     // 占空比(0-1000)
    uint8_t  channel_enable[PWM_CHANNELS]; // 通道使能标志
    uint8_t  polarity[PWM_CHANNELS];       // 极性(0:正,1:负)
} PWM_Data_t;

// 串口数据结构体
typedef struct {
   
    uint8_t rx_buffer[UART_BUFF_SIZE];     // 接收缓冲区
    uint8_t tx_buffer[UART_BUFF_SIZE];     // 发送缓冲区
    uint8_t rx_head;                       // 接收头指针
    uint8_t rx_tail;                       // 接收尾指针
    uint8_t tx_head;                       // 发送头指针
    uint8_t tx_tail;                       // 发送尾指针
    uint8_t frame_ready;                   // 帧就绪标志
    uint32_t last_rx_time;                 // 最后接收时间
} UART_Data_t;

// 系统配置结构体
typedef struct {
   
    SystemState_t system_state;            // 系统状态
    uint16_t adc_sample_rate;              // ADC采样率(Hz)
    uint8_t  uart_baud_rate[4];            // 串口波特率索引
    uint8_t  pwm_resolution;               // PWM分辨率
    uint8_t  watchdog_enable;              // 看门狗使能
    uint8_t  low_power_mode;               // 低功耗模式
} SystemConfig_t;

// 全局变量声明
extern ADC_Data_t adc_data;
extern PWM_Data_t pwm_data;
extern UART_Data_t uart_data[4];
extern SystemConfig_t sys_config;

// 函数声明
void System_Init(void);
void ADC_Init(void);
void PWM_Init(void);
void UART_Init(void);
void WatchDog_Init(void);
void System_Process(void);
void ADC_SampleAllChannels(void);
void ADC_FilterData(void);
void PWM_SetDutyCycle(uint8_t channel, uint16_t duty);
void PWM_SetFrequency(uint8_t channel, uint16_t freq);
void UART_SendString(uint8_t uart_num, char *str);
void UART_SendData(uint8_t uart_num, uint8_t *data, uint16_t len);
void UART_ProcessCommand(uint8_t uart_num);
void System_Sleep(void);
void System_Wakeup(void);

#endif /* __STC8_MULTIFUNC_H */

3.2 主程序 (main.c)

#include "stc8_multifunc.h"

// 全局变量定义
ADC_Data_t adc_data;
PWM_Data_t pwm_data;
UART_Data_t uart_data[4];
SystemConfig_t sys_config;

// 系统初始化
void System_Init(void) {
   
    // 关闭看门狗
    WDT_CONTR = 0x37;  // 禁止看门狗

    // 设置系统时钟为24MHz
    CLK_DIV = 0x00;    // 不分频,使用内部24MHz IRC

    // 初始化IO口
    P0M0 = 0x00; P0M1 = 0xFF;  // P0口全部设置为高阻输入(ADC)
    P1M0 = 0x00; P1M1 = 0xFF;  // P1口全部设置为高阻输入(ADC)
    P2M0 = 0xFF; P2M1 = 0x00;  // P2口全部设置为推挽输出(PWM)
    P3M0 = 0xFF; P3M1 = 0x00;  // P3口全部设置为推挽输出(串口)
    P4M0 = 0x00; P4M1 = 0x00;  // P4口准双向口

    // 初始化数据结构
    memset(&adc_data, 0, sizeof(ADC_Data_t));
    memset(&pwm_data, 0, sizeof(PWM_Data_t));
    memset(&uart_data, 0, sizeof(UART_Data_t)*4);
    memset(&sys_config, 0, sizeof(SystemConfig_t));

    // 设置默认配置
    sys_config.system_state = SYS_INIT;
    sys_config.adc_sample_rate = 1000;  // 1kHz采样率
    sys_config.uart_baud_rate[0] = 3;    // UART1: 115200
    sys_config.uart_baud_rate[1] = 3;    // UART2: 115200
    sys_config.uart_baud_rate[2] = 2;    // UART3: 57600
    sys_config.uart_baud_rate[3] = 1;    // UART4: 38400
    sys_config.pwm_resolution = 1000;     // 1000级分辨率
    sys_config.watchdog_enable = 0;       // 关闭看门狗
    sys_config.low_power_mode = 0;        // 关闭低功耗

    // 初始化各模块
    ADC_Init();
    PWM_Init();
    UART_Init();
    WatchDog_Init();

    // 使能所有ADC通道
    for(uint8_t i = 0; i < ADC_CHANNELS; i++) {
   
        adc_data.channel_enable[i] = 1;
    }

    // 使能所有PWM通道
    for(uint8_t i = 0; i < PWM_CHANNELS; i++) {
   
        pwm_data.channel_enable[i] = 1;
        pwm_data.frequency[i] = PWM_BASE_FREQ;
        pwm_data.duty_cycle[i] = 0;
    }

    sys_config.system_state = SYS_RUNNING;

    printf("System Initialized Successfully!\r\n");
    printf("STC8 Multi-function Data Acquisition System\r\n");
    printf("ADC Channels: 16, PWM Channels: 8, UART Ports: 4\r\n");
}

// 主循环
void main(void) {
   
    uint32_t last_adc_time = 0;
    uint32_t last_uart_time = 0;
    uint32_t system_tick = 0;

    // 系统初始化
    System_Init();

    while(1) {
   
        system_tick++;

        // ADC采样(1kHz)
        if(system_tick - last_adc_time >= 1000/sys_config.adc_sample_rate) {
   
            ADC_SampleAllChannels();
            ADC_FilterData();
            last_adc_time = system_tick;
        }

        // 串口数据处理
        if(system_tick - last_uart_time >= 10) {
     // 每10ms处理一次串口
            for(uint8_t i = 0; i < 4; i++) {
   
                if(uart_data[i].frame_ready) {
   
                    UART_ProcessCommand(i);
                    uart_data[i].frame_ready = 0;
                }
            }
            last_uart_time = system_tick;
        }

        // 系统处理
        System_Process();

        // 喂狗
        if(sys_config.watchdog_enable) {
   
            WDT_CONTR = 0x35;  // 喂狗
        }

        // 延时1ms
        Delay_ms(1);
    }
}

// 系统处理
void System_Process(void) {
   
    static uint32_t status_counter = 0;

    status_counter++;

    // 每秒发送一次状态
    if(status_counter >= 1000) {
   
        printf("ADC Sample Count: %lu\r\n", adc_data.sample_count);
        printf("ADC Channel 0: %.3fV, Channel 1: %.3fV\r\n", 
               adc_data.voltage[0], adc_data.voltage[1]);
        printf("PWM Duty Cycle: CH0=%d%%, CH1=%d%%\r\n", 
               pwm_data.duty_cycle[0]*100/pwm_data.frequency[0],
               pwm_data.duty_cycle[1]*100/pwm_data.frequency[1]);
        status_counter = 0;
    }
}

3.3 ADC 驱动 (adc_driver.c)

#include "stc8_multifunc.h"

// ADC初始化
void ADC_Init(void) {
   
    // 设置ADC时钟为系统时钟/2 = 12MHz
    ADCCFG = 0x0F;  // 设置ADC时钟为系统时钟/2

    // 设置ADC参考电压为内部2.5V
    ADC_CONTR = 0x80;  // 使能ADC模块

    // 延时等待ADC稳定
    Delay_ms(1);
}

// 读取单个ADC通道
uint16_t ADC_ReadChannel(uint8_t channel) {
   
    uint16_t adc_value = 0;

    // 设置ADC通道
    ADC_CONTR = (ADC_CONTR & 0xF0) | (channel & 0x0F);

    // 启动ADC转换
    ADC_CONTR |= 0x40;  // 启动ADC转换

    // 等待转换完成
    while(!(ADC_CONTR & 0x20));  // 等待转换完成标志

    // 读取ADC结果
    adc_value = (ADC_RES << 8) | ADC_RESL;

    // 清除转换完成标志
    ADC_CONTR &= ~0x20;

    return adc_value;
}

// 采样所有ADC通道
void ADC_SampleAllChannels(void) {
   
    uint16_t temp_value;
    uint32_t sum;

    for(uint8_t ch = 0; ch < ADC_CHANNELS; ch++) {
   
        if(!adc_data.channel_enable[ch]) continue;

        sum = 0;

        // 多次采样取平均
        for(uint8_t i = 0; i < ADC_SAMPLES; i++) {
   
            temp_value = ADC_ReadChannel(ch);
            sum += temp_value;
            Delay_us(10);
        }

        adc_data.raw_value[ch] = sum / ADC_SAMPLES;

        // 转换为电压值 (假设参考电压2.5V,12位ADC)
        adc_data.voltage[ch] = (float)adc_data.raw_value[ch] * 2.5f / 4096.0f;
    }

    adc_data.sample_count++;
}

// 中值滤波
uint16_t Median_Filter(uint16_t *buffer, uint8_t len) {
   
    uint16_t temp;
    uint8_t i, j;

    // 冒泡排序
    for(i = 0; i < len-1; i++) {
   
        for(j = 0; j < len-1-i; j++) {
   
            if(buffer[j] > buffer[j+1]) {
   
                temp = buffer[j];
                buffer[j] = buffer[j+1];
                buffer[j+1] = temp;
            }
        }
    }

    return buffer[len/2];  // 返回中值
}

// 数据滤波
void ADC_FilterData(void) {
   
    static uint16_t filter_buffer[ADC_CHANNELS][ADC_FILTER_LEN];
    static uint8_t filter_index = 0;
    uint16_t median_value;

    // 存储当前采样值到滤波缓冲区
    for(uint8_t ch = 0; ch < ADC_CHANNELS; ch++) {
   
        filter_buffer[ch][filter_index] = adc_data.raw_value[ch];
    }

    filter_index++;
    if(filter_index >= ADC_FILTER_LEN) {
   
        filter_index = 0;
    }

    // 对每个通道进行中值滤波
    for(uint8_t ch = 0; ch < ADC_CHANNELS; ch++) {
   
        median_value = Median_Filter(filter_buffer[ch], ADC_FILTER_LEN);
        adc_data.filtered[ch] = (float)median_value * 2.5f / 4096.0f;
    }
}

3.4 PWM 驱动 (pwm_driver.c)

#include "stc8_multifunc.h"

// PWM初始化
void PWM_Init(void) {
   
    uint16_t pwm_period;

    // 设置PWM时钟为系统时钟/12 = 2MHz
    PWMCKS = 0x0B;  // PWM时钟 = 系统时钟/12

    // 计算PWM周期值
    pwm_period = SYSCLK / 12 / PWM_BASE_FREQ;

    // 设置PWM周期
    PWMC = pwm_period;

    // 初始化所有PWM通道
    for(uint8_t i = 0; i < PWM_CHANNELS; i++) {
   
        // 设置PWM通道的初始占空比为0
        switch(i) {
   
            case 0: PWM0 = 0; break;
            case 1: PWM1 = 0; break;
            case 2: PWM2 = 0; break;
            case 3: PWM3 = 0; break;
            case 4: PWM4 = 0; break;
            case 5: PWM5 = 0; break;
            case 6: PWM6 = 0; break;
            case 7: PWM7 = 0; break;
        }

        // 设置PWM通道为独立模式
        switch(i) {
   
            case 0: PWM0CR = 0x00; break;  // PWM0独立模式
            case 1: PWM1CR = 0x00; break;  // PWM1独立模式
            case 2: PWM2CR = 0x00; break;  // PWM2独立模式
            case 3: PWM3CR = 0x00; break;  // PWM3独立模式
            case 4: PWM4CR = 0x00; break;  // PWM4独立模式
            case 5: PWM5CR = 0x00; break;  // PWM5独立模式
            case 6: PWM6CR = 0x00; break;  // PWM6独立模式
            case 7: PWM7CR = 0x00; break;  // PWM7独立模式
        }
    }

    // 使能PWM模块
    PWMCFG = 0x01;  // 使能PWM模块
}

// 设置PWM占空比
void PWM_SetDutyCycle(uint8_t channel, uint16_t duty) {
   
    uint16_t pwm_duty_value;

    // 限制占空比范围
    if(duty > sys_config.pwm_resolution) {
   
        duty = sys_config.pwm_resolution;
    }

    // 计算PWM比较值
    pwm_duty_value = (uint32_t)duty * PWMC / sys_config.pwm_resolution;

    // 设置对应通道的占空比
    switch(channel) {
   
        case 0: PWM0 = pwm_duty_value; break;
        case 1: PWM1 = pwm_duty_value; break;
        case 2: PWM2 = pwm_duty_value; break;
        case 3: PWM3 = pwm_duty_value; break;
        case 4: PWM4 = pwm_duty_value; break;
        case 5: PWM5 = pwm_duty_value; break;
        case 6: PWM6 = pwm_duty_value; break;
        case 7: PWM7 = pwm_duty_value; break;
    }

    pwm_data.duty_cycle[channel] = duty;
}

// 设置PWM频率
void PWM_SetFrequency(uint8_t channel, uint16_t freq) {
   
    uint16_t pwm_period;

    // 限制频率范围 (10Hz - 100kHz)
    if(freq < 10) freq = 10;
    if(freq > 100000) freq = 100000;

    // 计算PWM周期值
    pwm_period = SYSCLK / 12 / freq;

    // 更新PWM周期
    PWMC = pwm_period;

    pwm_data.frequency[channel] = freq;
}

// 设置PWM极性
void PWM_SetPolarity(uint8_t channel, uint8_t polarity) {
   
    switch(channel) {
   
        case 0: 
            if(polarity) PWM0CR |= 0x02;  // 负极性
            else PWM0CR &= ~0x02;         // 正极性
            break;
        case 1: 
            if(polarity) PWM1CR |= 0x02;
            else PWM1CR &= ~0x02;
            break;
        // ... 其他通道类似
    }

    pwm_data.polarity[channel] = polarity;
}

// 使能/禁用PWM通道
void PWM_EnableChannel(uint8_t channel, uint8_t enable) {
   
    switch(channel) {
   
        case 0: 
            if(enable) PWM0CR |= 0x01;
            else PWM0CR &= ~0x01;
            break;
        case 1: 
            if(enable) PWM1CR |= 0x01;
            else PWM1CR &= ~0x01;
            break;
        // ... 其他通道类似
    }

    pwm_data.channel_enable[channel] = enable;
}

3.5 串口驱动 (uart_driver.c)

#include "stc8_multifunc.h"

// 串口初始化
void UART_Init(void) {
   
    // 初始化UART1
    SCON = 0x50;     // 8位数据,可变波特率
    TMOD &= 0x0F;    // 清除定时器1模式位
    TMOD |= 0x20;    // 设置定时器1为模式2
    TH1 = 0xFD;      // 波特率115200
    TL1 = 0xFD;
    TR1 = 1;         // 启动定时器1
    ES = 1;         // 使能串口1中断

    // 初始化UART2 (使用定时器2)
    S2CON = 0x50;    // 8位数据,可变波特率
    T2L = 0xFD;      // 波特率115200
    T2H = 0xFD;
    AUXR |= 0x14;    // 启动定时器2
    IE2 |= 0x01;     // 使能串口2中断

    // 初始化UART3 (使用定时器3)
    S3CON = 0x50;    // 8位数据,可变波特率
    T3L = 0xFA;      // 波特率57600
    T3H = 0xFA;
    T4T3M |= 0x02;   // 启动定时器3
    IE2 |= 0x04;     // 使能串口3中断

    // 初始化UART4 (使用定时器4)
    S4CON = 0x50;    // 8位数据,可变波特率
    T4L = 0xF6;      // 波特率38400
    T4H = 0xF6;
    T4T3M |= 0x20;   // 启动定时器4
    IE2 |= 0x10;     // 使能串口4中断

    EA = 1;          // 使能总中断
}

// 串口发送单个字节
void UART_SendByte(uint8_t uart_num, uint8_t dat) {
   
    switch(uart_num) {
   
        case 0:  // UART1
            SBUF = dat;
            while(!TI);
            TI = 0;
            break;
        case 1:  // UART2
            S2BUF = dat;
            while(!(S2CON & 0x02));
            S2CON &= ~0x02;
            break;
        case 2:  // UART3
            S3BUF = dat;
            while(!(S3CON & 0x02));
            S3CON &= ~0x02;
            break;
        case 3:  // UART4
            S4BUF = dat;
            while(!(S4CON & 0x02));
            S4CON &= ~0x02;
            break;
    }
}

// 串口发送字符串
void UART_SendString(uint8_t uart_num, char *str) {
   
    while(*str) {
   
        UART_SendByte(uart_num, *str++);
    }
}

// 串口发送数据
void UART_SendData(uint8_t uart_num, uint8_t *data, uint16_t len) {
   
    for(uint16_t i = 0; i < len; i++) {
   
        UART_SendByte(uart_num, data[i]);
    }
}

// 串口接收中断处理
void UART_ProcessReceive(uint8_t uart_num, uint8_t dat) {
   
    UART_Data_t *uart = &uart_data[uart_num];

    // 存储接收到的数据
    uart->rx_buffer[uart->rx_head] = dat;
    uart->rx_head = (uart->rx_head + 1) % UART_BUFF_SIZE;

    // 检查是否接收到帧结束符
    if(dat == '\n' || dat == '\r') {
   
        uart->frame_ready = 1;
    }

    uart->last_rx_time = Get_SystemTick();
}

// 串口命令处理
void UART_ProcessCommand(uint8_t uart_num) {
   
    UART_Data_t *uart = &uart_data[uart_num];
    char cmd_buffer[64];
    uint8_t len = 0;

    // 提取命令字符串
    while(uart->rx_tail != uart->rx_head && len < sizeof(cmd_buffer)-1) {
   
        cmd_buffer[len] = uart->rx_buffer[uart->rx_tail];
        uart->rx_tail = (uart->rx_tail + 1) % UART_BUFF_SIZE;
        len++;
    }
    cmd_buffer[len] = '\0';

    // 解析命令
    if(strstr(cmd_buffer, "ADC")) {
   
        UART_SendString(uart_num, "ADC Values:\r\n");
        for(uint8_t i = 0; i < ADC_CHANNELS; i++) {
   
            char response[64];
            sprintf(response, "CH%d: %.3fV\r\n", i, adc_data.voltage[i]);
            UART_SendString(uart_num, response);
        }
    }
    else if(strstr(cmd_buffer, "PWM")) {
   
        uint8_t channel;
        uint16_t duty;
        sscanf(cmd_buffer, "PWM %d %d", &channel, &duty);
        if(channel < PWM_CHANNELS) {
   
            PWM_SetDutyCycle(channel, duty);
            char response[64];
            sprintf(response, "PWM%d set to %d%%\r\n", channel, duty*100/sys_config.pwm_resolution);
            UART_SendString(uart_num, response);
        }
    }
    else if(strstr(cmd_buffer, "HELP")) {
   
        UART_SendString(uart_num, "Available Commands:\r\n");
        UART_SendString(uart_num, "ADC - Show ADC values\r\n");
        UART_SendString(uart_num, "PWM <ch> <duty> - Set PWM duty\r\n");
        UART_SendString(uart_num, "STATUS - Show system status\r\n");
        UART_SendString(uart_num, "RESET - Reset system\r\n");
    }
    else if(strstr(cmd_buffer, "STATUS")) {
   
        char response[128];
        sprintf(response, "System State: %d\r\n", sys_config.system_state);
        UART_SendString(uart_num, response);
        sprintf(response, "ADC Samples: %lu\r\n", adc_data.sample_count);
        UART_SendString(uart_num, response);
    }
}

// 串口中断服务函数
void UART1_ISR(void) interrupt 4 {
   
    uint8_t dat;

    if(RI) {
   
        RI = 0;
        dat = SBUF;
        UART_ProcessReceive(0, dat);
    }
}

void UART2_ISR(void) interrupt 8 {
   
    uint8_t dat;

    if(S2CON & 0x01) {
   
        S2CON &= ~0x01;
        dat = S2BUF;
        UART_ProcessReceive(1, dat);
    }
}

void UART3_ISR(void) interrupt 17 {
   
    uint8_t dat;

    if(S3CON & 0x01) {
   
        S3CON &= ~0x01;
        dat = S3BUF;
        UART_ProcessReceive(2, dat);
    }
}

void UART4_ISR(void) interrupt 18 {
   
    uint8_t dat;

    if(S4CON & 0x01) {
   
        S4CON &= ~0x01;
        dat = S4BUF;
        UART_ProcessReceive(3, dat);
    }
}

3.6 看门狗和系统管理 (system_manager.c)

#include "stc8_multifunc.h"

// 看门狗初始化
void WatchDog_Init(void) {
   
    if(sys_config.watchdog_enable) {
   
        WDT_CONTR = 0x37;  // 使能看门狗,设置预分频
    }
}

// 系统休眠
void System_Sleep(void) {
   
    sys_config.system_state = SYS_SLEEP;

    // 关闭不必要的外设
    PWMCFG = 0x00;  // 关闭PWM
    ADC_CONTR = 0x00;  // 关闭ADC

    // 进入掉电模式
    PCON |= 0x02;  // 进入掉电模式
    _nop_();
    _nop_();
}

// 系统唤醒
void System_Wakeup(void) {
   
    sys_config.system_state = SYS_RUNNING;

    // 重新初始化外设
    PWM_Init();
    ADC_Init();
}

// 系统复位
void System_Reset(void) {
   
    // 软件复位
    IAP_CONTR = 0x60;  // 软件复位
}

// 延时函数
void Delay_ms(uint16_t ms) {
   
    uint16_t i, j;
    for(i = 0; i < ms; i++) {
   
        for(j = 0; j < 1200; j++) {
   
            _nop_();
        }
    }
}

void Delay_us(uint16_t us) {
   
    while(us--) {
   
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}

// 获取系统滴答计数
uint32_t Get_SystemTick(void) {
   
    static uint32_t tick = 0;
    static uint16_t last_count = 0;
    uint16_t current_count = TH0;  // 使用定时器0作为系统滴答

    if(current_count < last_count) {
   
        tick += 65536;
    }
    last_count = current_count;

    return tick + current_count;
}

参考代码 STC8 16通道模拟采集、4路串口通讯、8路PWM程序 www.youwenfan.com/contentali/60707.html

四、工程配置与使用

4.1 编译配置

Keil C51 工程配置:
• Target: STC8A8K64S4A12
• Code Rom Size: Large
• Xdata Ram Size: 8192
• Memory Model: Large
• Code Optimization: Level 8 (Maximum)

4.2 使用示例

// 示例:控制PWM输出呼吸灯效果
void BreathingLED(void) {
   
    static uint16_t duty = 0;
    static uint8_t direction = 0;

    if(direction == 0) {
   
        duty++;
        if(duty >= 1000) {
   
            direction = 1;
        }
    } else {
   
        duty--;
        if(duty == 0) {
   
            direction = 0;
        }
    }

    PWM_SetDutyCycle(0, duty);  // PWM0控制LED
    Delay_ms(5);
}

// 示例:读取ADC并通过串口发送
void ADC_Report(void) {
   
    char report[128];

    sprintf(report, "ADC Report:\r\n");
    UART_SendString(0, report);

    for(uint8_t i = 0; i < 16; i++) {
   
        if(adc_data.channel_enable[i]) {
   
            sprintf(report, "CH%d: %.3fV (Raw: %d)\r\n", 
                   i, adc_data.voltage[i], adc_data.raw_value[i]);
            UART_SendString(0, report);
        }
    }
}

4.3 常见问题解决

问题 原因 解决方案
ADC读数不稳定 电源噪声干扰 增加电源滤波电容,使用外部参考电压
PWM输出不正常 频率设置错误 检查PWM时钟分频和周期设置
串口通信失败 波特率不匹配 确认系统时钟频率,重新计算波特率
系统经常复位 看门狗超时 增加喂狗频率,检查程序死循环
目录
相关文章
|
2月前
|
算法 语音技术 数据安全/隐私保护
语音更改技术:变调与变速的原理及实现
语音更改技术:变调与变速的原理及实现
324 1
|
2月前
|
存储 编解码 边缘计算
LTE标准下Turbo码编译码仿真
LTE标准下Turbo码编译码仿真
238 4
|
3月前
|
安全 前端开发 数据可视化
如何选择适合你的建站系统
这是一篇关于如何选择建站系统的指南。文章从明确需求、评估技术预算入手,介绍了易用性、灵活性等核心对比维度,并简要分析了全托管平台、自助建站系统及手工编码等主流方式的适用场景。
164 1
|
数据采集 人工智能 供应链
《AI赋能工业制造:开启智能生产新时代》
在新一轮科技革命中,人工智能(AI)与工业制造深度融合,推动制造业迈向智能化、数字化新时代。AI通过智能生产调度、设备故障预测、质量检测和供应链优化等应用,显著提升效率和创新能力。特斯拉和富士康的智能工厂展示了AI在实际生产中的巨大潜力。然而,数据质量、技术集成和人才短缺等问题仍需解决。未来,AI将与5G、物联网等技术融合,进一步推动工业制造全面升级。
1113 9
|
监控 JavaScript 安全
vue3添加pinia
本文介绍了Pinia作为Vue 3的状态管理库的特点,包括其基于Vue 3的Composition API、响应式状态管理、零依赖设计、插件系统、Devtools集成、Tree-shakable特性以及对TypeScript的支持,并详细说明了如何在Vue 3项目中安装和初始化Pinia。
421 1
vue3添加pinia
|
网络协议 网络虚拟化 数据中心
VLAN和VXLAN,两者有何区别
随着网络技术发展,云计算因其高利用率、低管理成本及灵活性成为各行业IT建设新趋势。服务器虚拟化作为核心技术之一,提升了数据中心计算密度,但传统二三层网络难以满足虚拟机无限制迁移需求。VLAN技术因支持VLAN数有限,无法满足云服务商需求;而VXLAN技术通过将二层网络扩展到三层,可支持多达1600万个网络,有效克服了VLAN的局限性,实现多租户支持和网络可靠性的提升。
593 1
|
Python
将NC栅格表示时间维度的数据提取出来的方法
【10月更文挑战第20天】本文介绍了如何使用 Python 和 R 语言以及 ArcGIS 软件提取 netCDF 文件中的时间维度数据。首先,通过安装和导入必要的库(如 Python 的 `netCDF4` 和 `numpy`,R 的 `ncdf4`),打开 netCDF 文件并读取时间变量。接着,详细展示了 Python 和 R 的示例代码,说明了如何读取和处理时间数据。最后,介绍了在 ArcGIS 中添加 netCDF 文件、启用时间属性并提取时间维度数据的方法。
863 1
|
机器学习/深度学习 XML 调度