STC芯片常用代码

提供STC芯片的示例代码和常用功能实现,方便开发者参考和使用

GPIO操作

LED闪烁

控制LED灯的闪烁,是最基础的GPIO操作示例。

LED闪烁代码

#include <STC89C52.h>

// 延时函数
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--);
}

void main() {
    // 设置P1.0为输出
    P1 = 0xFF;  // 初始化P1口
    
    while (1) {
        P1 &= ~0x01;  // 点亮LED
        delay(500);   // 延时500ms
        P1 |= 0x01;   // 熄灭LED
        delay(500);   // 延时500ms
    }
}
                            
代码特点:
  • 简单易懂,适合入门学习
  • 包含基本的延时函数实现
  • 演示了GPIO的输出操作
使用场景:

LED指示灯、状态指示、系统运行状态显示

按键检测

检测按键的按下和释放,实现按键输入功能。

按键检测代码

#include <STC89C52.h>

// 延时函数
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--);
}

void main() {
    // 设置P1.0为输出(LED),P3.2为输入(按键)
    P1 = 0xFF;
    P3 = 0xFF;
    
    while (1) {
        if (!(P3 & 0x04)) {  // 检测按键是否按下
            delay(10);       // 消抖
            if (!(P3 & 0x04)) {  // 再次检测
                P1 &= ~0x01;  // 点亮LED
                while (!(P3 & 0x04));  // 等待按键释放
                P1 |= 0x01;   // 熄灭LED
            }
        }
    }
}
                            
代码特点:
  • 包含按键消抖处理
  • 演示了GPIO的输入操作
  • 实现了按键状态的检测
使用场景:

用户输入、功能切换、参数调整

串口通信

串口发送

通过串口发送数据,实现与上位机的通信。

串口发送代码

#include <STC89C52.h>

// 串口初始化
void UART_Init() {
    SCON = 0x50;  // 设置为模式1(8位UART)
    TMOD = 0x20;  // 设置定时器1为模式2(自动重装载)
    TH1 = 0xFD;   // 波特率9600,晶振11.0592MHz
    TL1 = 0xFD;
    TR1 = 1;      // 启动定时器1
    EA = 1;       // 开启总中断
}

// 发送单个字符
void UART_SendChar(unsigned char c) {
    SBUF = c;
    while (!TI);  // 等待发送完成
    TI = 0;       // 清除发送标志
}

// 发送字符串
void UART_SendString(unsigned char *str) {
    while (*str) {
        UART_SendChar(*str++);
    }
}

void main() {
    UART_Init();
    
    while (1) {
        UART_SendString("Hello STC!\r\n");
        // 延时
        unsigned int i, j;
        for (i = 1000; i > 0; i--)
            for (j = 110; j > 0; j--);
    }
}
                            
代码特点:
  • 包含串口初始化配置
  • 实现了单个字符和字符串的发送
  • 波特率设置为9600,适用于大多数场景
使用场景:

数据上传、调试信息输出、与上位机通信

串口接收

通过串口接收数据,实现与上位机的双向通信。

串口接收代码

#include <STC89C52.h>

unsigned char received_data;

// 串口初始化
void UART_Init() {
    SCON = 0x50;  // 设置为模式1(8位UART)
    TMOD = 0x20;  // 设置定时器1为模式2(自动重装载)
    TH1 = 0xFD;   // 波特率9600,晶振11.0592MHz
    TL1 = 0xFD;
    TR1 = 1;      // 启动定时器1
    EA = 1;       // 开启总中断
    ES = 1;       // 开启串口中断
}

// 发送单个字符
void UART_SendChar(unsigned char c) {
    SBUF = c;
    while (!TI);  // 等待发送完成
    TI = 0;       // 清除发送标志
}

// 串口中断服务函数
void UART_ISR() interrupt 4 {
    if (RI) {     // 接收中断
        received_data = SBUF;  // 读取接收的数据
        RI = 0;               // 清除接收标志
        UART_SendChar(received_data);  // 回显接收到的数据
    }
}

void main() {
    UART_Init();
    
    while (1) {
        // 主循环可以做其他事情
    }
}
                            
代码特点:
  • 使用中断方式接收数据
  • 实现了数据的回显功能
  • 串口初始化配置完整
使用场景:

接收上位机命令、参数配置、远程控制

定时器使用

定时器中断

使用定时器中断实现精确的时间控制。

定时器中断代码

#include <STC89C52.h>

unsigned int count = 0;

// 定时器0初始化
void Timer0_Init() {
    TMOD = 0x01;  // 设置定时器0为模式1(16位定时器)
    TH0 = (65536 - 50000) / 256;  // 定时50ms,晶振11.0592MHz
    TL0 = (65536 - 50000) % 256;
    EA = 1;       // 开启总中断
    ET0 = 1;      // 开启定时器0中断
    TR0 = 1;      // 启动定时器0
}

// 定时器0中断服务函数
void Timer0_ISR() interrupt 1 {
    TH0 = (65536 - 50000) / 256;  // 重新加载初值
    TL0 = (65536 - 50000) % 256;
    count++;
    
    if (count >= 20) {  // 1秒(50ms * 20)
        count = 0;
        P1 ^= 0x01;  // 翻转LED状态
    }
}

void main() {
    Timer0_Init();
    
    while (1) {
        // 主循环可以做其他事情
    }
}
                            
代码特点:
  • 使用定时器中断实现精确计时
  • 定时时间可根据需要调整
  • 演示了中断服务函数的编写
使用场景:

定时任务、精确延时、频率测量

ADC转换

ADC读取

使用ADC模块读取模拟信号,实现电压测量等功能。

ADC读取代码(以STC12C5A60S2为例)

#include <STC12C5A60S2.h>

// ADC初始化
void ADC_Init() {
    P1ASF = 0x01;  // 设置P1.0为ADC输入通道
    ADC_RES = 0;   // 清除ADC结果寄存器
    ADC_CONTR = 0x80;  // 开启ADC电源
}

// 读取ADC值
unsigned int ADC_Read(unsigned char channel) {
    ADC_CONTR = 0x80 | (channel << 3) | 0x08;  // 选择通道并启动转换
    _nop_();
    _nop_();
    while (!(ADC_CONTR & 0x10));  // 等待转换完成
    ADC_CONTR &= ~0x10;  // 清除转换完成标志
    return (ADC_RES << 8) | ADC_RESL;  // 返回10位ADC值
}

void main() {
    unsigned int adc_value;
    
    ADC_Init();
    
    while (1) {
        adc_value = ADC_Read(0);  // 读取通道0的值
        // 处理ADC值,比如显示或发送
    }
}
                            
代码特点:
  • 实现了ADC的初始化和读取
  • 支持通道选择
  • 返回10位ADC值
使用场景:

电压测量、传感器信号采集、模拟量处理

PWM输出

PWM控制

使用PWM输出实现LED亮度调节、电机速度控制等功能。

PWM控制代码(以STC12C5A60S2为例)

#include <STC12C5A60S2.h>

// PWM初始化
void PWM_Init() {
    P1M1 &= ~0x01;  // 设置P1.0为推挽输出
    P1M2 |= 0x01;
    
    // 设置定时器1为PWM模式
    TMOD &= 0x0F;
    TMOD |= 0x20;  // 定时器1为模式2(8位自动重装载)
    
    TH1 = 0xFF;  //  PWM周期
    TL1 = 0xFF;
    
    // 设置PCA/PWM
    CMOD = 0x00;  // PCA时钟为系统时钟/12
    CL = 0x00;    // 清除PCA计数器
    CH = 0x00;
    
    // 设置PWM0
    CCAPM0 = 0x42;  // 开启PWM0,无中断
    CCAP0L = 0x80;  // PWM占空比50%
    CCAP0H = 0x80;
    
    CR = 1;  // 启动PCA计数器
}

// 设置PWM占空比
void PWM_SetDuty(unsigned char duty) {
    CCAP0L = duty;
    CCAP0H = duty;
}

void main() {
    unsigned char duty = 0;
    bit direction = 1;
    
    PWM_Init();
    
    while (1) {
        if (direction) {
            duty++;
            if (duty >= 0xFF) {
                direction = 0;
            }
        } else {
            duty--;
            if (duty <= 0) {
                direction = 1;
            }
        }
        
        PWM_SetDuty(duty);
        
        // 延时
        unsigned int i, j;
        for (i = 10; i > 0; i--)
            for (j = 110; j > 0; j--);
    }
}
                            
代码特点:
  • 实现了PWM的初始化和占空比设置
  • 演示了PWM亮度渐变效果
  • 适用于STC12系列芯片
使用场景:

LED亮度调节、电机速度控制、蜂鸣器音量控制

代码使用说明

如何使用这些代码

  1. 根据您使用的STC芯片型号,选择相应的代码示例
  2. 将代码复制到您的开发环境中
  3. 根据实际硬件连接,修改相应的引脚定义
  4. 编译并下载到芯片中运行

注意事项

  • 不同系列的STC芯片,寄存器定义可能有所不同,请参考相应的芯片 datasheet
  • 代码中的晶振频率设置可能需要根据实际使用的晶振进行调整
  • 对于复杂的功能,可能需要结合多个代码示例进行实现
  • 在使用中断时,注意中断优先级和嵌套问题

扩展建议

  • 将常用功能封装成函数,提高代码的可重用性
  • 使用结构体和枚举类型,提高代码的可读性
  • 添加适当的注释,方便后期维护
  • 考虑代码的健壮性,添加错误处理机制