打印
[PIC®/AVR®/dsPIC®产品]

Microchip PIC16F877A MCU在按键控制LED和UART通信中的应用

[复制链接]
747|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Uriah|  楼主 | 2024-10-11 13:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

Microchip的MCU以其稳定性和多功能性在嵌入式开发领域享有很高的声誉,PIC16F877A作为其经典的8位MCU,广泛应用于家电控制、工业自动化和物联网等领域。本文将介绍PIC16F877A MCU在按键控制LED和UART通信中的应用,并提供相关代码实现。

PIC16F877A简介PIC16F877A是Microchip公司推出的一款高性能8位微控制器,基于RISC架构,指令执行速度快,内置多个外设,如ADC、串口、I2C、SPI等,具有较大的RAM和EEPROM存储空间。该MCU主要适用于低功耗控制系统,支持多个中断源,适合需要实时响应的嵌入式应用。

硬件设计本应用场景包括以下硬件模块:
  • MCU型号:Microchip PIC16F877A
  • 功能模块:按键控制LED、串口通信
  • 开发环境:MPLAB X IDE + XC8编译器
应用目标是实现通过按键控制LED的亮灭,并通过UART将LED的状态信息发送至上位机进行调试。

代码实现以下代码展示了如何通过PIC16F877A控制GPIO口实现按键控制LED,以及通过UART发送状态信息。
#include <xc.h>

// 配置位设置
#pragma config FOSC = HS   // 晶体振荡器
#pragma config WDTE = OFF  // 关闭看门狗定时器
#pragma config PWRTE = OFF // 关闭上电延时定时器
#pragma config BOREN = ON  // 使能掉电复位
#pragma config LVP = OFF   // 禁用低电压编程
#pragma config CPD = OFF   // 关闭数据EEPROM的代码保护
#pragma config WRT = OFF   // 禁用闪存写保护
#pragma config CP = OFF    // 关闭程序存储器的代码保护

#define _XTAL_FREQ 20000000  // 定义系统频率

// 定义引脚
#define LED_PIN PORTBbits.RB0   // LED连接到RB0引脚
#define BUTTON_PIN PORTBbits.RB1 // 按键连接到RB1引脚

// 函数声明
void System_Init(void);
void GPIO_Init(void);
void UART_Init(void);
void LED_Toggle(void);
void UART_Write(char data);
void UART_Write_String(char *str);

void main(void)
{
    // 初始化系统
    System_Init();
    // 初始化GPIO
    GPIO_Init();
    // 初始化UART
    UART_Init();
   
    // 主循环
    while (1)
    {
        // 检测按键状态
        if (BUTTON_PIN == 0) // 按键按下
        {
            __delay_ms(50); // 防抖延时
            if (BUTTON_PIN == 0)
            {
                // 切换LED状态
                LED_Toggle();
                // 通过串口发送LED状态信息
                UART_Write_String("LED Toggled!\r\n");
                // 等待按键释放
                while (BUTTON_PIN == 0);
            }
        }
    }
}

// 系统初始化
void System_Init(void)
{
    // 配置系统时钟
    OSCCON = 0x71;  // 设置内部振荡器频率为8MHz
}

// GPIO初始化
void GPIO_Init(void)
{
    TRISBbits.TRISB0 = 0;  // 配置RB0为输出引脚
    TRISBbits.TRISB1 = 1;  // 配置RB1为输入引脚
    LED_PIN = 0;           // 初始化LED状态为灭
}

// UART初始化
void UART_Init(void)
{
    TRISCbits.TRISC6 = 0;  // 配置RC6为TX输出引脚
    TRISCbits.TRISC7 = 1;  // 配置RC7为RX输入引脚
   
    // 配置波特率
    SPBRG = 31;            // 设置波特率为9600(20MHz晶振)
    TXSTAbits.BRGH = 1;    // 高波特率
    RCSTAbits.SPEN = 1;    // 使能串口
    TXSTAbits.TXEN = 1;    // 使能发送
    RCSTAbits.CREN = 1;    // 使能接收
}

// LED状态切换
void LED_Toggle(void)
{
    LED_PIN = ~LED_PIN;    // 切换LED状态
}

// 串口发送单字节
void UART_Write(char data)
{
    while (!TXSTAbits.TRMT);  // 等待发送缓冲区空
    TXREG = data;             // 发送数据
}

// 串口发送字符串
void UART_Write_String(char *str)
{
    while (*str)
    {
        UART_Write(*str++);
    }
}

代码说明
  • 系统初始化:通过System_Init()函数配置系统时钟,使MCU工作在合适的频率下。在本例中,我们使用20MHz的外部晶振。
  • GPIO初始化:通过GPIO_Init()函数,将RB0引脚配置为输出,用于控制LED的状态;RB1引脚配置为输入,用于检测按键状态。
  • 串口初始化:UART_Init()函数设置波特率为9600,串口使用RC6引脚作为发送(TX),RC7引脚作为接收(RX)。
  • 按键控制LED:在主循环中,检测按键按下时,调用LED_Toggle()函数切换LED的亮灭状态,并通过串口发送“LED Toggled!”的状态信息。
  • 防抖处理:在按键检测中,我们使用了一个简单的延时防抖,避免按键抖动引起误操作。
  • 串口通信:通过UART_Write()和UART_Write_String()函数,向上位机发送LED状态的文本信息,方便调试和状态反馈。


扩展功能
  • ADC应用:PIC16F877A带有10位ADC模块,可以通过ADC读取传感器数据,并通过UART发送至上位机进行监控。
  • PWM控制:可以通过配置CCP模块输出PWM信号,用于控制电机或调节LED的亮度。
  • 定时器中断:利用定时器中断来处理一些实时任务,例如定时采集数据或控制定时闪烁。
  • I2C通信:PIC16F877A支持I2C通信,可以扩展I2C设备,如EEPROM、温湿度传感器等。


总结Microchip的PIC16F877A MCU在嵌入式系统中应用广泛,其丰富的外设资源和较高的性价比,使其成为许多中小型嵌入式项目的首选。本篇文章通过按键控制LED和串口通信的代码示例,展示了如何使用该MCU进行简单的控制与通信。随着项目的复杂度提升,可以进一步利用PIC16F877A的其他功能模块实现更多的应用场景。

使用特权

评论回复
沙发
Uriah|  楼主 | 2024-10-11 13:33 | 只看该作者
我刚好手头有个PIC16F877A的开发板,可以直接跟着你这个代码做实验了。

使用特权

评论回复
板凳
周半梅| | 2024-10-11 13:34 | 只看该作者
串口通信这一块解释得挺清楚,学到了不少。

使用特权

评论回复
地板
公羊子丹| | 2024-10-11 13:34 | 只看该作者
你这防抖处理虽然简单,但对很多项目来说已经够用了。

使用特权

评论回复
5
帛灿灿| | 2024-10-11 13:34 | 只看该作者
我之前没用过Microchip的MCU,看完感觉挺容易上手的。

使用特权

评论回复
6
童雨竹| | 2024-10-11 13:34 | 只看该作者
我觉得用这个PIC16F877A来做家电控制是个不错的选择。

使用特权

评论回复
7
Wordsworth| | 2024-10-11 13:35 | 只看该作者
PWM调光可以再试一下,毕竟现在很多地方都用到这个。

使用特权

评论回复
8
Pulitzer| | 2024-10-11 13:35 | 只看该作者
你提到的定时器中断功能很实用,我可以试着加到我的项目中。

使用特权

评论回复
9
Bblythe| | 2024-10-11 13:35 | 只看该作者
这个代码挺简洁的,没想到可以实现这么多功能。

使用特权

评论回复
10
Clyde011| | 2024-10-11 13:35 | 只看该作者
能不能再加个I2C通信的例子?我项目里用到这块比较多。

使用特权

评论回复
11
Bblythe| | 2024-10-11 13:36 | 只看该作者
这篇文章对我帮助很大,特别是串口调试那部分!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

3765

帖子

0

粉丝