找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2|回复: 0
收起左侧

求助:采用485采集风速和温度只能采一样

[复制链接]
回帖奖励 5 黑币 回复本帖可获得 5 黑币奖励! 每人限 1 次
ID:1151496 发表于 2026-3-18 18:27 | 显示全部楼层 |阅读模式
本帖最后由 小桥流水不 于 2026-3-18 18:33 编辑

  使用stc15f2k48s2单片机,485接收温湿度和风速,如果把Task1_Run里的//        if (currentTime - lastWindTime >= 1000)//        {
//            lastWindTime = currentTime;
//            ModbusMasterSendWindData();
//            windStep = 1;
//            windStartTime = currentTime;
//            printf("发送风速请求...\n");
//        }
    }屏蔽,能收到温湿度数据,如果不屏蔽,只能收到风速和风力数据
ebd880824a66e78736e301a2a758291f.jpg 5cc10eb4e213afe7f37d3f5282df37c0.jpg

这是代码:

#include        "config.h"
#include        "timer.h"
#include        "USART.h"
#include        "delay.h"
#include "stdio.h"
#include        "GPIO.h"
#include "modbus_send_receive.h"
#include "modbus_crc.h"
#include "lcd12864.h"
#include "task_1.h"

/*************        功能说明        **************

双串口全双工中断方式收发通讯程序。
串口1使用串口通讯,串口2使用RS485通讯

通过PC向MCU发送数据, MCU收到后通过串口把收到的数据通过原路返回.
两个串口同时使用定时器2做为波特率发生器,两个串口的波特率相同,如果需要不同波特率,
需改变串口1配置定时器,串口2固定使用定时器2做为波特率发生器
串口1波特率:9600
串口2波特率:9600


开机lcd12864第一行显示“风速测量”
                        第二行显示风速:和风速值
                        第三行显示风力:和风力等级
                        
                        采用rs485和风速传感器通讯,主机发送 01 03 00 00 00 02 C4 0B
            “01”代表仪表地址。修改此地址可以和不同地址的仪表通信。
                        “03”modbus.功能码,使用03“0000” 仪表内部存器地址(即0x0000+0x01)
                        “0002”代表一次读取2组数据
                        “C40B”CRC校验,计算得到
                        此指令的意思是“用功能码03读取仪表地址为01的内部寄存器地址01(即0x00+0x01)开始的2个单位的数据”

           从机回复:01 03 04 00 02 00 01 9A 33
                   说明:
                        “01”代表仪表地址
                        “03”代表modbus功能码
                        “04”代表后面4字节为对应仪表参数“0002”表示当前风速0x02=2,即0.02米/秒(默认2位小数点)
                        
                        收到回复后将数值解析显示在LCD12864上,也通过串口1打印到pc上
                        
                        rs485采用串口2,波特率9600,串口发送接收控制引脚 :P12 在USART.h定义

******************************************/




xdata unsigned char str1[] = {"风速:"};
xdata unsigned char str2[] = {"风力:    级"};
xdata unsigned char str3[] = {"温度:    "};
xdata unsigned char str4[] = {"℃"};
xdata unsigned char str5[] = {"湿度:"};
xdata unsigned char str6[] = {" %"};


void main(void)
{
        u8        i;

        Timer_config();
        UART_config();
        GPIO_config();
        Lcd12864_Init();
        EA = 1;

        Task1_Init();
        printf("Init is finish\n");
        while (1)
        {
               
               


                Task1_Run();
                delay_ms(1);
//                if(COM1.RX_TimeOut > 0)                //超时计数
//                {
//                        if(--COM1.RX_TimeOut == 0)
//                        {
//                                if(COM1.RX_Cnt > 0)
//                                {
//                                        for(i=0; i<COM1.RX_Cnt; i++)        
//                                        {
//                                                TX1_write2buff(RX1_Buffer);        //收到的数据通过串口1发送
//                                        }
//                                }
//                                COM1.RX_Cnt = 0;

//                        }
//                }

        }
}





#include "task_1.h"
#include "lcd12864.h"
#include "delay.h"
#include "modbus_send_receive.h"
#include "stdio.h"
#include "timer.h"
#include "USART.h"


/**
* @brief 风速显示函数
*/
void WindSpeed_Display(u16 speed, u8 row, u8 position)
{

    xdata unsigned char digit[4] = {0};
    u8 lcd_row = row;

    // 边界值处理:超过3690显示无效
    if(speed > 3690)   
    {
        Lcd12864_SetPos(lcd_row, position);
        Lcd12864_WriteDat('-');
        Lcd12864_WriteDat('.');
        Lcd12864_WriteDat('-');
        Lcd12864_WriteDat('-');
        Lcd12864_WriteDat(' ');
                Lcd12864_WriteDat('m');
        Lcd12864_WriteDat('/');
        Lcd12864_WriteDat('s');
        return;
    }

    // 拆分四位数字(千/百/十/个)
    digit[0] = (speed / 1000) % 10;
    digit[1] = (speed / 100) % 10;
    digit[2] = (speed / 10) % 10;
    digit[3] = speed % 10;

    // 设置显示位置
    Lcd12864_SetPos(lcd_row, position);

    // 显示整数部分(处理前导0)
    if(digit[0] == 0 && digit[1] == 0)
    {
        Lcd12864_WriteDat('0');
    }
    else
    {
        if(digit[0] != 0)
        {
            Lcd12864_WriteDat(digit[0] + '0');
        }
        Lcd12864_WriteDat(digit[1] + '0');
    }

    // 小数点+小数部分
    Lcd12864_WriteDat('.');
    Lcd12864_WriteDat(digit[2] + '0');
    Lcd12864_WriteDat(digit[3] + '0');

    // 单位
    Lcd12864_WriteDat(' ');
        Lcd12864_WriteDat('m');
    Lcd12864_WriteDat('/');
    Lcd12864_WriteDat('s');
}

/**
* @brief 风级显示函数
*/
void WindLevel_Display(u16 level, u8 row, u8 position)
{
    xdata unsigned char digit[2] = {0};
    u8 lcd_row = row;

    // 风级边界处理(0~12级)
    if(level > 12)
    {
        Lcd12864_SetPos(lcd_row, position);
        Lcd12864_WriteDat('-');
        Lcd12864_WriteDat('-');

        return;
    }

    // 拆分风级数字
    digit[0] = (level / 10) % 10; // 十位
    digit[1] = level % 10;        // 个位

    Lcd12864_SetPos(lcd_row, position);

    // 显示风级(处理前导0)
    if(digit[0] == 0)
    {
        Lcd12864_WriteDat(' '); // 十位为0时显示空格
    }
    else
    {
        Lcd12864_WriteDat(digit[0] + '0');
    }
    Lcd12864_WriteDat(digit[1] + '0');

}

/**
* @brief 温度显示函数
*/
void Temperature_Display(int temp_value, u8 row, u8 position)
{
    u8 digit[3];
    u8 neg_flag = 0;

    if (temp_value < 0)
    {
        neg_flag = 1;
        temp_value = -temp_value;
    }

    digit[0] = (temp_value / 100) % 10;
    digit[1] = (temp_value / 10) % 10;
    digit[2] = temp_value % 10;

    Lcd12864_SetPos(row, position);

    if (neg_flag)
        Lcd12864_WriteDat('-');
    else
        Lcd12864_WriteDat(' ');

    if (digit[0] == 0)
        Lcd12864_WriteDat(' ');
    else
        Lcd12864_WriteDat(digit[0] + '0');

    Lcd12864_WriteDat(digit[1] + '0');
    Lcd12864_WriteDat('.');
    Lcd12864_WriteDat(digit[2] + '0');
}

/**
* @brief 湿度显示函数
*/
void Humidity_Display(u16 humi_value, u8 row, u8 position)
{
    u8 digit[3];

    digit[0] = (humi_value / 100) % 10;
    digit[1] = (humi_value / 10) % 10;
    digit[2] = humi_value % 10;

    Lcd12864_SetPos(row, position);

    if (digit[0] == 0)
        Lcd12864_WriteDat(' ');
    else
        Lcd12864_WriteDat(digit[0] + '0');

    Lcd12864_WriteDat(digit[1] + '0');
    Lcd12864_WriteDat('.');
    Lcd12864_WriteDat(digit[2] + '0');
}

/**
* @brief 任务1初始化
*/
void Task1_Init(void)
{
    Lcd12864_WriteCmd(0x01); // 清屏
    delay_ms(20);

    // 显示静态文本
    Lcd12864_SetPos(1, 1); Lcd12864_WriteCN(str1);
    Lcd12864_SetPos(2, 1); Lcd12864_WriteCN(str2);

    Lcd12864_SetPos(3, 1); Lcd12864_WriteCN(str3);
    Lcd12864_SetPos(3, 7); Lcd12864_WriteCN(str4);  // "C"
    Lcd12864_SetPos(4, 1); Lcd12864_WriteCN(str5);
    Lcd12864_SetPos(4, 6); Lcd12864_WriteCN(str6);  // "%"

    // 初始显示0值
    WindSpeed_Display(0, 1, 4);
    WindLevel_Display(0, 2, 4);
    Temperature_Display(0, 3, 4);
    Humidity_Display(0, 4, 4);

    Modbus_ClearBuffer();
    printf("Task1初始化完成\n");
}

/**
* @brief 任务1运行 - 修正版(双独立状态机)
*/
void Task1_Run(void)
{
    static u32 lastWindTime = 0;
    static u32 lastTempTime = 0;
    static u16 lastWindSpeed = 0;
    static u16 lastWindLevel = 0;
    static int lastTemp = 0;
    static u16 lastHumi = 0;

    // 风速独立状态
    static u8 windStep = 0;  // 0:空闲, 1:等待响应
    static u32 windStartTime = 0;

    // 温湿度独立状态
    static u8 tempStep = 0;  // 0:空闲, 1:等待响应
    static u32 tempStartTime = 0;

    u32 currentTime = GetSysTimeMs();
        
        

        

    // ========== 风速处理(独立) ==========
    if (windStep == 0)
    {
        // 空闲状态,检查是否需要发送
        if (currentTime - lastWindTime >= 1000)
        {
            lastWindTime = currentTime;
            ModbusMasterSendWindData();
            windStep = 1;
            windStartTime = currentTime;
            printf("发送风速请求...\n");
        }
    }
    else if (windStep == 1)
    {
        // 等待风速响应
        ModbusMasterReceiveWind();

        // 超时处理(500ms)
        if (currentTime - windStartTime > 500)
        {
            printf("风速响应超时\n");
            windStep = 0;
            COM2.RX_Cnt = 0;
        }
        // 接收完成
        else if (COM2.RX_TimeOut == 0 && COM2.RX_Cnt == 0)
        {
            windStep = 0;
        }
    }

                // ========== 温湿度处理(独立) ==========
    if (tempStep == 0)
    {
        // 空闲状态,检查是否需要发送
        if (currentTime - lastTempTime >= 3000)
        {
            lastTempTime = currentTime;
            ModbusMasterSendTempHumiData();
            tempStep = 1;
            tempStartTime = currentTime;
            printf("发送温湿度请求...\n");
        }
    }
    else if (tempStep == 1)
    {
        // 等待温湿度响应
        ModbusMasterReceiveTempHumi();

        // 超时处理(500ms)
        if (currentTime - tempStartTime > 500)
        {
            printf("温湿度响应超时\n");
            tempStep = 0;
            COM2.RX_Cnt = 0;
        }
        // 接收完成
        else if (COM2.RX_TimeOut == 0 && COM2.RX_Cnt == 0)
        {
            tempStep = 0;
        }
    }
        

    // 心跳灯
    if (currentTime % 500 < 50)
    {
        P00 = 0;
    }
    else
    {
        P00 = 1;
    }

    // 更新LCD显示(仅在数据变化时)
    if (windSpeed != lastWindSpeed || windLevel != lastWindLevel)
    {
        WindSpeed_Display(windSpeed, 1, 4);
        WindLevel_Display(windLevel, 2, 4);
        printf("LCD更新 - 风速:%u(%.2f) 风级:%u\n",
               windSpeed, windSpeed*0.01f, windLevel);
        lastWindSpeed = windSpeed;
        lastWindLevel = windLevel;
    }

    if (temp != lastTemp || humi != lastHumi)
    {
        Temperature_Display(temp, 3, 4);
        Humidity_Display(humi, 4, 4);
        printf("LCD更新 - 温度:%d.%d℃ 湿度:%u.%u%%\n",
               temp/10, (temp<0 ? -(temp%10) : temp%10),
               humi/10, humi%10);
        lastTemp = temp;
        lastHumi = humi;
    }
}







#ifndef __TASK_1_H
#define __TASK_1_H

#include "config.h"

// 字符串声明
extern xdata unsigned char str1[];
extern xdata unsigned char str2[];
extern xdata unsigned char str3[];
extern xdata unsigned char str4[];
extern xdata unsigned char str5[];
extern xdata unsigned char str6[];

// 函数声明
void Task1_Init(void);
void Task1_Run(void);
void WindSpeed_Display(u16 speed, u8 row, u8 position);
void WindLevel_Display(u16 level, u8 row, u8 position);
void Temperature_Display(int temp_value, u8 row, u8 position);
void Humidity_Display(u16 humi_value, u8 row, u8 position);

#endif







#include "string.h"
#include "modbus_send_receive.h"
#include "timer.h"
#include "stdio.h"
#include "delay.h"
#include "USART.h"
#include "modbus_crc.h"
#include "GPIO.h"

// 全局变量定义
u32 sendFreTime = 0;
u8 xdata sendBuf[8] = {0};
u8 xdata receiveBuf[9] = {0};
u8 xdata temp_humi_buf[9] = {0};  // 温湿度专用接收缓冲区
u16 windSpeed = 0;
u16 windLevel = 0;
int temp = 0;    // 温度,有符号整数
u16 humi = 0;       // 湿度,无符号整数

/**
* @brief  清除接收缓冲区
*/
void Modbus_ClearBuffer(void)
{
    COM2.RX_Cnt = 0;
    COM2.RX_TimeOut = 0;
    memset(receiveBuf, 0, sizeof(receiveBuf));
    memset(temp_humi_buf, 0, sizeof(temp_humi_buf));
}

/**
* @brief  组装风速读取指令(地址0x01)
*/
void ModbusMasterSetWindCmd(void)
{
    u16 crc;

    sendBuf[0] = SLAVE_ADDR_WIND;        // 从机地址 0x01
    sendBuf[1] = FUNC_READ_HOLD_REGS;    // 功能码 0x03
    sendBuf[2] = 0x00;                   // 寄存器起始地址高字节
    sendBuf[3] = REG_ADDR_START;         // 寄存器起始地址低字节 0x00
    sendBuf[4] = 0x00;                   // 寄存器数量高字节
    sendBuf[5] = REG_COUNT_READ;         // 寄存器数量低字节 0x02

    crc = ModbusCRC16(sendBuf, 6);
    sendBuf[6] = (u8)(crc & 0xFF);       // CRC低字节
    sendBuf[7] = (u8)(crc >> 8);         // CRC高字节
}

/**
* @brief  发送风速读取指令
*/
void ModbusMasterSendWindData(void)
{
    u8 i = 0;

    ModbusMasterSetWindCmd();

    printf("\n发送风速指令: ");
    for (i = 0; i < 8; i++)
    {
        TX2_write2buff(sendBuf);
        printf("%bx ", sendBuf);
    }
    printf("\n");
}

/**
* @brief  接收并解析风速/风级
*/
void ModbusMasterReceiveWind(void)
{
    u16 crc_calc;
    u8 len;
    u8 i;

    if (COM2.RX_TimeOut == 0)
    {
        printf("风速超时,无数据\n");
        return;
    }

    if (--COM2.RX_TimeOut == 0)
    {
        if (COM2.RX_Cnt > 0)
        {
            len = COM2.RX_Cnt;

            printf("风速原始数据(%d): ", len);
            for(i=0; i<len; i++)
            {
                printf("%bx ", RX2_Buffer);
            }
            printf("\n");

            // 检查长度
            if (len != 9)
            {
                printf("风速长度错误: %d, 期望9\n", len);
                COM2.RX_Cnt = 0;
                return;
            }

            // 复制数据
            for(i=0; i<9; i++) receiveBuf = RX2_Buffer;

            // 打印解析的数据
            printf("解析: 地址=%bx, 功能码=%bx, 长度=%bx, ",
                   receiveBuf[0], receiveBuf[1], receiveBuf[2]);
            printf("数据=%bx%bx %bx%bx, CRC=%bx%bx\n",
                   receiveBuf[3], receiveBuf[4], receiveBuf[5], receiveBuf[6],
                   receiveBuf[7], receiveBuf[8]);

            // 地址校验
            if(receiveBuf[0] != SLAVE_ADDR_WIND)
            {
                printf("风速地址错误: 期望%bx, 收到%bx\n",
                       SLAVE_ADDR_WIND, receiveBuf[0]);
                COM2.RX_Cnt = 0;
                return;
            }

            // 功能码校验
            if(receiveBuf[1] != FUNC_READ_HOLD_REGS)
            {
                printf("风速功能码错误\n");
                COM2.RX_Cnt = 0;
                return;
            }

            // CRC校验
            crc_calc = ModbusCRC16(receiveBuf, 7);
            if(receiveBuf[7] == (u8)(crc_calc & 0xFF) &&
               receiveBuf[8] == (u8)(crc_calc >> 8))
            {
                windSpeed = (u16)receiveBuf[3] << 8 | receiveBuf[4];
                windLevel = (u16)receiveBuf[5] << 8 | receiveBuf[6];

                printf("风速解析成功: %u (%.2f m/s), 风级: %u\n",
                       windSpeed, windSpeed * 0.01f, windLevel);
            }
            else
            {
                printf("风速CRC错误: 计算=%u, 收到=%bx%bx\n",
                       crc_calc, receiveBuf[8], receiveBuf[7]);
            }

            COM2.RX_Cnt = 0;
        }
        else
        {
            printf("风速接收缓冲区为空\n");
        }
    }
}

/**
* @brief  组装温湿度读取指令(地址0x02)
*/
void ModbusMasterSetTempHumiCmd(void)
{
    u16 crc;

    sendBuf[0] = SLAVE_ADDR_TEMP_HUMI;   // 从机地址 0x02
    sendBuf[1] = FUNC_READ_HOLD_REGS;    // 功能码 0x03
    sendBuf[2] = 0x00;                   // 寄存器起始地址高字节
    sendBuf[3] = REG_ADDR_START;         // 寄存器起始地址低字节 0x00
    sendBuf[4] = 0x00;                   // 寄存器数量高字节
    sendBuf[5] = REG_COUNT_READ;         // 寄存器数量低字节 0x02

    crc = ModbusCRC16(sendBuf, 6);
    sendBuf[6] = (u8)(crc & 0xFF);       // CRC低字节
    sendBuf[7] = (u8)(crc >> 8);         // CRC高字节
}

/**
* @brief  发送温湿度读取指令
*/
void ModbusMasterSendTempHumiData(void)
{
    u8 i = 0;

    ModbusMasterSetTempHumiCmd();

    printf("\n发送温湿度指令: ");
    for (i = 0; i < 8; i++)
    {
        TX2_write2buff(sendBuf);
        printf("%bX ", sendBuf);
    }
    printf("\n");
}

/**
* @brief  接收并解析温湿度
*/
void ModbusMasterReceiveTempHumi(void)
{
    u16 crc_calc;
    u8 len;
        u8 i;
    u16 raw_temp;
        

    if (COM2.RX_TimeOut == 0) return;

    if (--COM2.RX_TimeOut == 0)
    {
        if (COM2.RX_Cnt > 0)
        {
            len = COM2.RX_Cnt;
            memcpy(temp_humi_buf, RX2_Buffer, len);

            printf("收到温湿度数据(%d字节): ", len);
            for( i=0; i<len; i++) printf("%bX ", temp_humi_buf);
            printf("\n");

            // 校验数据长度
            if (len != 9)
            {
                printf("温湿度长度错误: %d, 期望9字节\n", len);
                COM2.RX_Cnt = 0;
                return;
            }

            // 地址和功能码校验
            if (temp_humi_buf[0] != SLAVE_ADDR_TEMP_HUMI ||
                temp_humi_buf[1] != FUNC_READ_HOLD_REGS)
            {
                printf("温湿度地址/功能码错误: Addr=0x%bX, Func=0x%bX\n",
                       temp_humi_buf[0], temp_humi_buf[1]);
                COM2.RX_Cnt = 0;
                return;
            }

            // 数据长度校验
            if (temp_humi_buf[2] != 0x04)
            {
                printf("温湿度数据长度错误: 0x%bX\n", temp_humi_buf[2]);
                COM2.RX_Cnt = 0;
                return;
            }

            // CRC校验
            crc_calc = ModbusCRC16(temp_humi_buf, 7);
            if (temp_humi_buf[7] == (u8)(crc_calc & 0xFF) &&
                temp_humi_buf[8] == (u8)(crc_calc >> 8))
            {
                // 解析数据:前两个字节是湿度,后两个字节是温度
                humi = (u16)temp_humi_buf[3] << 8 | temp_humi_buf[4];
                raw_temp = (u16)temp_humi_buf[5] << 8 | temp_humi_buf[6];

                // 温度可能是带符号的(如果传感器支持负温度)
                if (raw_temp > 0x7FFF)
                {
                    temp = (int)(raw_temp - 0x10000);
                }
                else
                {
                    temp = (int)raw_temp;
                }

                printf("温湿度解析成功: 湿度=%u.%u%%, 温度=%d.%d℃\n",
                       humi/10, humi%10,
                       temp/10, (temp < 0 ? -temp%10 : temp%10));
            }
            else
            {
                printf("温湿度CRC错误! 计算: 0x%bX, 收到: 0x%bX%bX\n",
                       crc_calc, temp_humi_buf[8], temp_humi_buf[7]);
            }

            COM2.RX_Cnt = 0;
        }
    }
}





#ifndef        __MODBUS_SEND_RECEIVE_H
#define        __MODBUS_SEND_RECEIVE_H

#include        "config.h"

// 协议相关宏定义
#define SLAVE_ADDR_WIND         0x01    // 风速传感器地址
#define SLAVE_ADDR_TEMP_HUMI    0x02    // 温湿度传感器地址
#define FUNC_READ_HOLD_REGS     0x03    // 读保持寄存器功能码
#define REG_ADDR_START          0x00    // 寄存器起始地址
#define REG_COUNT_READ          0x02    // 要读取的寄存器数量

// ==================== 全局变量声明 ====================
extern u32 sendFreTime;                     // 串口发送数据间隔
extern u8 xdata sendBuf[8];                 // 发送缓冲区
extern u8 xdata receiveBuf[9];              // 风速接收缓冲区
extern u8 xdata temp_humi_buf[9];           // 温湿度接收缓冲区
extern u16 windSpeed;                       // 风速值 (单位: 0.01 m/s)
extern u16 windLevel;                       // 风级值
extern int temp;                      // 温度值 (单位: 0.1℃)
extern u16 humi;                         // 湿度值 (单位: 0.1%)

// ==================== 函数声明 ====================
/**
* @brief  组装风速读取指令
*/
void ModbusMasterSetWindCmd(void);

/**
* @brief  发送风速读取指令
*/
void ModbusMasterSendWindData(void);

/**
* @brief  接收并解析风速/风级
*/
void ModbusMasterReceiveWind(void);

/**
* @brief  组装温湿度读取指令
*/
void ModbusMasterSetTempHumiCmd(void);

/**
* @brief  发送温湿度读取指令
*/
void ModbusMasterSendTempHumiData(void);

/**
* @brief  接收并解析温湿度
*/
void ModbusMasterReceiveTempHumi(void);

/**
* @brief  清除接收缓冲区
*/
void Modbus_ClearBuffer(void);

#endif








#include "USART.h"
#include "stdio.h"
#include        "delay.h"






COMx_Define        COM1,COM2;
u8        xdata TX1_Buffer[COM_TX1_Lenth];        //发送缓冲
u8         xdata RX1_Buffer[COM_RX1_Lenth];        //接收缓冲
u8        xdata TX2_Buffer[COM_TX2_Lenth];        //发送缓冲
u8         xdata RX2_Buffer[COM_RX2_Lenth];        //接收缓冲

u8 USART_Configuration(u8 UARTx, COMx_InitDefine *COMx)
{
        u8        i;
        u32        j;
        
        if(UARTx == USART1)
        {
                COM1.id = 1;
                COM1.TX_read    = 0;
                COM1.TX_write   = 0;
                COM1.B_TX_busy  = 0;
                COM1.RX_Cnt     = 0;
                COM1.RX_TimeOut = 0;
                COM1.B_RX_OK    = 0;
                for(i=0; i<COM_TX1_Lenth; i++)        TX1_Buffer = 0;
                for(i=0; i<COM_RX1_Lenth; i++)        RX1_Buffer = 0;

                if(COMx->UART_Mode > UART_9bit_BRTx)        return 2;        //模式错误
                if(COMx->UART_Polity == PolityHigh)                PS = 1;        //高优先级中断
                else                                                                        PS = 0;        //低优先级中断
                SCON = (SCON & 0x3f) | COMx->UART_Mode;
                if((COMx->UART_Mode == UART_9bit_BRTx) ||(COMx->UART_Mode == UART_8bit_BRTx))        //可变波特率
                {
                        j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;        //按1T计算
                        if(j >= 65536UL)        return 2;        //错误
                        j = 65536UL - j;
                        if(COMx->UART_BRT_Use == BRT_Timer1)
                        {
                                TR1 = 0;
                                AUXR &= ~0x01;                //S1 BRT Use Timer1;
                                TMOD &= ~(1<<6);        //Timer1 set As Timer
                                TMOD &= ~0x30;                //Timer1_16bitAutoReload;
                                AUXR |=  (1<<6);        //Timer1 set as 1T mode
                                TH1 = (u8)(j>>8);
                                TL1 = (u8)j;
                                ET1 = 0;        //禁止中断
                                TMOD &= ~0x40;        //定时
                                INT_CLKO &= ~0x02;        //不输出时钟
                                TR1  = 1;
                        }
                        else if(COMx->UART_BRT_Use == BRT_Timer2)
                        {
                                AUXR &= ~(1<<4);        //Timer stop
                                AUXR |= 0x01;                //S1 BRT Use Timer2;
                                AUXR &= ~(1<<3);        //Timer2 set As Timer
                                AUXR |=  (1<<2);        //Timer2 set as 1T mode
                                TH2 = (u8)(j>>8);
                                TL2 = (u8)j;
                                IE2  &= ~(1<<2);        //禁止中断
                                AUXR &= ~(1<<3);        //定时
                                AUXR |=  (1<<4);        //Timer run enable
                        }
                        else return 2;        //错误
                }
                else if(COMx->UART_Mode == UART_ShiftRight)
                {
                        if(COMx->BaudRateDouble == ENABLE)        AUXR |=  (1<<5);        //固定波特率SysClk/2
                        else                                                                AUXR &= ~(1<<5);        //固定波特率SysClk/12
                }
                else if(COMx->UART_Mode == UART_9bit)        //固定波特率SysClk*2^SMOD/64
                {
                        if(COMx->BaudRateDouble == ENABLE)        PCON |=  (1<<7);        //固定波特率SysClk/32
                        else                                                                PCON &= ~(1<<7);        //固定波特率SysClk/64
                }
                if(COMx->UART_Interrupt == ENABLE)        ES = 1;        //允许中断
                else                                                                ES = 0;        //禁止中断
                if(COMx->UART_RxEnable == ENABLE)        REN = 1;        //允许接收
                else                                                                REN = 0;        //禁止接收
                P_SW1 = (P_SW1 & 0x3f) | (COMx->UART_P_SW & 0xc0);        //切换IO
                if(COMx->UART_RXD_TXD_Short == ENABLE)        PCON2 |=  (1<<4);        //内部短路RXD与TXD, 做中继, ENABLE,DISABLE
                else                                                                        PCON2 &= ~(1<<4);
                return        0;
        }

        if(UARTx == USART2)
        {
                COM2.id = 2;
                COM2.TX_read    = 0;
                COM2.TX_write   = 0;
                COM2.B_TX_busy  = 0;
                COM2.RX_Cnt     = 0;
                COM2.RX_TimeOut = 0;
                COM2.B_RX_OK    = 0;
                for(i=0; i<COM_TX2_Lenth; i++)        TX2_Buffer = 0;
                for(i=0; i<COM_RX2_Lenth; i++)        RX2_Buffer = 0;

                if((COMx->UART_Mode == UART_9bit_BRTx) ||(COMx->UART_Mode == UART_8bit_BRTx))        //可变波特率
                {
                        if(COMx->UART_Polity == PolityHigh)                IP2 |=  1;        //高优先级中断
                        else                                                                        IP2 &= ~1;        //低优先级中断
                        if(COMx->UART_Mode == UART_9bit_BRTx)        S2CON |=  (1<<7);        //9bit
                        else                                                                        S2CON &= ~(1<<7);        //8bit
                        j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;        //按1T计算
                        if(j >= 65536UL)        return 2;        //错误
                        j = 65536UL - j;
                        AUXR &= ~(1<<4);        //Timer stop
                        AUXR &= ~(1<<3);        //Timer2 set As Timer
                        AUXR |=  (1<<2);        //Timer2 set as 1T mode
                        TH2 = (u8)(j>>8);
                        TL2 = (u8)j;
                        IE2  &= ~(1<<2);        //禁止中断
                        AUXR |=  (1<<4);        //Timer run enable
                }
                else        return 2;        //模式错误
                if(COMx->UART_Interrupt == ENABLE)        IE2   |=  1;                //允许中断
                else                                                                IE2   &= ~1;                //禁止中断
                if(COMx->UART_RxEnable == ENABLE)        S2CON |=  (1<<4);        //允许接收
                else                                                                S2CON &= ~(1<<4);        //禁止接收
                P_SW2 = (P_SW2 & ~1) | (COMx->UART_P_SW & 0x01);        //切换IO
        }
}


/*************** 装载串口发送缓冲 *******************************/

void TX1_write2buff(u8 dat)        //写入发送缓冲,指针+1
{
        TX1_Buffer[COM1.TX_write] = dat;        //装发送缓冲
        if(++COM1.TX_write >= COM_TX1_Lenth)        COM1.TX_write = 0;

        if(COM1.B_TX_busy == 0)                //空闲
        {  
                COM1.B_TX_busy = 1;                //标志忙
                TI = 1;                                        //触发发送中断
        }
}

void TX2_write2buff(u8 dat)        //写入发送缓冲,指针+1
{
    // 关键修改:只在发送第一个字节时切换485方向
    if (COM2.B_TX_busy == 0)  // 空闲状态,即将开始发送
    {
        RS485_DIR_PIN = RS485_TX_MODE;  // 切到发送模式
        delay_us(200);  // 重要!延时等待485芯片切换完成(200微秒)
    }

    TX2_Buffer[COM2.TX_write] = dat;
    if(++COM2.TX_write >= COM_TX2_Lenth) COM2.TX_write = 0;

    if(COM2.B_TX_busy == 0)                //空闲
    {  
        COM2.B_TX_busy = 1;                //标志忙
        SET_TI2();                                //触发发送中断
    }
}


void PrintString1(u8 *puts)
{
    for (; *puts != 0;        puts++)  TX1_write2buff(*puts);         //遇到停止符0结束
}

void PrintString2(u8 *puts)
{
    for (; *puts != 0;        puts++)  TX2_write2buff(*puts);         //遇到停止符0结束
}

/*
void COMx_write2buff(COMx_Define *COMx, u8 dat)        //写入发送缓冲,指针+1
{
        if(COMx->id == 1)        TX1_write2buff(dat);
        if(COMx->id == 2)        TX2_write2buff(dat);
}

void PrintString(COMx_Define *COMx, u8 *puts)
{
    for (; *puts != 0;        puts++)  COMx_write2buff(COMx,*puts);         //遇到停止符0结束
}
*/


/********************* UART1中断函数************************/
void UART1_int (void) interrupt UART1_VECTOR
{
        if(RI)
        {
                RI = 0;
                if(COM1.B_RX_OK == 0)
                {
                        if(COM1.RX_Cnt >= COM_RX1_Lenth)        COM1.RX_Cnt = 0;
                        RX1_Buffer[COM1.RX_Cnt++] = SBUF;
                        COM1.RX_TimeOut = TimeOutSet1;
                }
        }

        if(TI)
        {
                TI = 0;
                if(COM1.TX_read != COM1.TX_write)
                {
                         SBUF = TX1_Buffer[COM1.TX_read];
                        if(++COM1.TX_read >= COM_TX1_Lenth)                COM1.TX_read = 0;
                }
                else        COM1.B_TX_busy = 0;
        }
}

/********************* UART2中断函数************************/
void UART2_int (void) interrupt UART2_VECTOR
{
    if(RI2)  // 接收中断
    {
        CLR_RI2();

        // 收到数据时,强制切回接收模式(确保模式正确)
        RS485_DIR_PIN = RS485_RX_MODE;

        if(COM2.B_RX_OK == 0)
        {
            if(COM2.RX_Cnt < COM_RX2_Lenth)  // 防止缓冲区溢出
            {
                RX2_Buffer[COM2.RX_Cnt++] = S2BUF;
                COM2.RX_TimeOut = TimeOutSet2;
            }
            else
            {
                // 缓冲区满,清空
                COM2.RX_Cnt = 0;
                RX2_Buffer[COM2.RX_Cnt++] = S2BUF;
                COM2.RX_TimeOut = TimeOutSet2;
            }
        }
    }

    if(TI2)  // 发送中断
    {
        CLR_TI2();

        if(COM2.TX_read != COM2.TX_write)
        {
            // 还有数据要发送
            S2BUF = TX2_Buffer[COM2.TX_read];
            if(++COM2.TX_read >= COM_TX2_Lenth) COM2.TX_read = 0;
        }
        else        
        {
            // 所有数据发送完毕
            COM2.B_TX_busy = 0;

            // 关键修改:延时等待最后1字节发送完成
            // 波特率9600时,1字节约1.04ms,延时1.5ms确保安全
            delay_ms(2);  // 2ms延时,确保最后1字节完全发出

            // 切换回接收模式
            RS485_DIR_PIN = RS485_RX_MODE;
        }
    }
}

char putchar(char c)
{

    if(c == '\n')
    {
        TX1_write2buff('\r');
    }
    TX1_write2buff((u8)c); // 对接硬件串口的发送缓冲,触发中断发送
    return c; // 按C51标准要求返回,无实际意义
}












#ifndef __USART_H
#define __USART_H         

#include        "config.h"


// ********* 485方向控制定义 *********
#define RS485_DIR_PIN   P12        // 485 DE/RE控制引脚(根据你的硬件修改)
#define RS485_TX_MODE   1          // 发送模式:DE=1, RE=1
#define RS485_RX_MODE   0          // 接收模式:DE=0, RE=0



#define        COM_TX1_Lenth        128
#define        COM_RX1_Lenth        128
#define        COM_TX2_Lenth        128
#define        COM_RX2_Lenth        128

#define        USART1        1
#define        USART2        2

#define        UART_ShiftRight        0                //同步移位输出
#define        UART_8bit_BRTx        (1<<6)        //8位数据,可变波特率
#define        UART_9bit                (2<<6)        //9位数据,固定波特率
#define        UART_9bit_BRTx        (3<<6)        //9位数据,可变波特率

#define        UART1_SW_P30_P31        0
#define        UART1_SW_P36_P37        (1<<6)
#define        UART1_SW_P16_P17        (2<<6)        //必须使用内部时钟
#define        UART2_SW_P10_P11        0
#define        UART2_SW_P46_P47        1


#define        TimeOutSet1                5
#define        TimeOutSet2                5

#define        BRT_Timer1        1
#define        BRT_Timer2        2

typedef struct
{
        u8        id;                                //串口号

        u8        TX_read;                //发送读指针
        u8        TX_write;                //发送写指针
        u8        B_TX_busy;                //忙标志

        u8         RX_Cnt;                        //接收字节计数
        u8        RX_TimeOut;                //接收超时
        u8        B_RX_OK;                //接收块完成
} COMx_Define;

typedef struct
{
        u8        UART_Mode;                        //模式,         UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
        u8        UART_BRT_Use;                //使用波特率,   BRT_Timer1,BRT_Timer2
        u32        UART_BaudRate;                //波特率,       ENABLE,DISABLE
        u8        Morecommunicate;        //多机通讯允许, ENABLE,DISABLE
        u8        UART_RxEnable;                //允许接收,   ENABLE,DISABLE
        u8        BaudRateDouble;                //波特率加倍, ENABLE,DISABLE
        u8        UART_Interrupt;                //中断控制,   ENABLE,DISABLE
        u8        UART_Polity;                //优先级,     PolityLow,PolityHigh
        u8        UART_P_SW;                        //切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)
        u8        UART_RXD_TXD_Short;        //内部短路RXD与TXD, 做中继, ENABLE,DISABLE

} COMx_InitDefine;

extern        COMx_Define        COM1,COM2;
extern        u8        xdata TX1_Buffer[COM_TX1_Lenth];        //发送缓冲
extern        u8         xdata RX1_Buffer[COM_RX1_Lenth];        //接收缓冲
extern        u8        xdata TX2_Buffer[COM_TX2_Lenth];        //发送缓冲
extern        u8         xdata RX2_Buffer[COM_RX2_Lenth];        //接收缓冲

u8        USART_Configuration(u8 UARTx, COMx_InitDefine *COMx);
void TX1_write2buff(u8 dat);        //写入发送缓冲,指针+1
void TX2_write2buff(u8 dat);        //写入发送缓冲,指针+1
void PrintString1(u8 *puts);
void PrintString2(u8 *puts);

//void COMx_write2buff(COMx_Define *COMx, u8 dat);        //写入发送缓冲,指针+1
//void PrintString(COMx_Define *COMx, u8 *puts);
char putchar(char c);


#endif









#include "lcd12864.h"
#include        "delay.h"




sbit CS   = P3^2;     // 串行片选端:1=有效,0=无效        (对应并行输入的RS)
sbit SID  = P3^3;     // 串行数据端:收发数据              (对应并行输入的RW)
sbit SCK  = P3^4;     // 串行时钟端:上升沿锁存数据        (对应并行输入的E)
//sbit RST  = P3^5;     // 硬件复位端:0=复位,1=正常工作    (对应并行输入的RST)
// sbit PSB = P1^3;  // 串口模式→硬件必须直接接GND,此引脚无效

/**
***********************************************************
* @brief     串行接收1字节数据(参考代码适配,ST7920标准)
* @return    拼接后的8位有效数据
* @note      连续读2字节,高4位+低4位拼接,适配ST7920串口读数据时序
***********************************************************/
static unsigned char ReceiveByte(void)
{
    unsigned char i, temp1, temp2;
    temp1 = temp2 = 0;
    // 读高4位相关数据
    for(i=0; i<8; i++)
    {
        temp1 = temp1 << 1;
        SCK = 0;
        SCK = 1;               
        SCK = 0;
        if(SID) temp1++;
    }
    // 读低4位相关数据
    for(i=0; i<8; i++)
    {
        temp2 = temp2 << 1;
        SCK = 0;
        SCK = 1;
        SCK = 0;
        if(SID) temp2++;
    }
    return ((0xF0 & temp1) + (0x0F & temp2)); // 拼接为8位有效数据
}

/**
***********************************************************
* @brief     串行发送1字节数据(参考代码核心,ST7920标准时序)
* @param     dat:要发送的8位字节
* @note      
***********************************************************/
static void Lcd_SendByte(unsigned char dat)
{
    unsigned char i;
    for(i=0; i<8; i++)
    {
        SCK = 0;            // 下降沿准备数据

        SID = (dat & 0x80) != 0;  // 直接取最高位
        dat = dat << 1;

        SCK = 1;            // 上升沿锁存数据
        SCK = 0;            // 时钟归0,参考代码标准操作
    }
}

/**
***********************************************************
* @brief     检测LCD12864忙信号(参考代码适配,无卡死)
* @note      发0xFC读忙前缀,循环判断bit7,直到LCD空闲
***********************************************************/
void Lcd_12864_BusyCheck()
{
    do
    {
        Lcd_SendByte(0xFC); // 串行读忙前缀:11111 RW(1) RS(0) 0
    }while(0x80 & ReceiveByte()); // bit7=1则忙,循环等待
}

/**
***********************************************************
* @brief     向LCD12864写入命令(参考代码核心,ST7920标准)
* @param     cmd:要写入的命令字(ST7920指令集)
* @note      CS片选→忙检测→发前缀→高4位→低4位→CS失选,严格按手册
***********************************************************/
void Lcd12864_WriteCmd(unsigned char cmd)
{
    CS = 1;                // 片选有效
    Lcd_12864_BusyCheck(); // 忙检测,参考代码逻辑无卡死
    Lcd_SendByte(0xF8);    // 串行写命令固定前缀:11111 RW(0) RS(0) 0
    Lcd_SendByte(0xF0 & cmd); // 发送命令高4位(屏蔽低4位)
    Lcd_SendByte(0xF0 & (cmd << 4)); // 发送命令低4位(左移后屏蔽)
    CS = 0;                // 片选无效,完成命令写入
    delay_ms(1);           // 短延时,保证指令执行
}

/**
***********************************************************
* @brief     向LCD12864写入数据(参考代码核心,ST7920标准)
* @param     dat:要写入的8位数据(汉字双字节/ASCII字符)
* @note      写数据前缀0xFA,其余逻辑与写命令一致
***********************************************************/
void Lcd12864_WriteDat(unsigned char dat)
{
    CS = 1;                // 片选有效
    Lcd_12864_BusyCheck(); // 忙检测
    Lcd_SendByte(0xFA);    // 串行写数据固定前缀:11111 RW(0) RS(1) 0
    Lcd_SendByte(0xF0 & dat); // 发送数据高4位
    Lcd_SendByte(0xF0 & (dat << 4)); // 发送数据低4位
    CS = 0;                // 片选无效
    delay_ms(1);           // 短延时,保证数据锁存
}

/**
***********************************************************
* @brief     LCD12864初始化函数(参考代码标准串口流程,必显!)
* @note      完全对齐参考代码的初始化指令,复位+3次0x30+标准配置
***********************************************************/
void Lcd12864_Init(void)
{

//    RST = 0;
//    delay_ms(100);  // 参考代码用100ms延时,保证硬件复位彻底
//    RST = 1;
//    delay_ms(100);  // 复位后稳定时间

    // 参考代码核心:连续3次发0x30,确保ST7920识别并进入基础指令集
    Lcd12864_WriteCmd(0x30);
    delay_ms(100);
    Lcd12864_WriteCmd(0x30);
    delay_ms(100);
    Lcd12864_WriteCmd(0x30);
    delay_ms(100);

    // 参考代码标准后续配置,按顺序执行
    Lcd12864_WriteCmd(0x03);  // 入口模式设置
    delay_ms(50);
    Lcd12864_WriteCmd(0x01);  // 清屏
    delay_ms(100);
    Lcd12864_WriteCmd(0x06);  // 光标移动方向配置
    delay_ms(100);
    Lcd12864_WriteCmd(0x0C);  // 开显示、关光标、关闪烁
    delay_ms(100);
}

// 以下2个函数:完全保留你的代码,无任何修改!!!
/**
***********************************************************
* @brief     LCD12864显示位置定位函数
* @param     x:目标显示行号,有效范围1~4(LCD共4行)
* @param     y:目标显示列号,有效范围1~8(中文专属,1汉字占2列)
* @return    无
* @note      x/y越界时直接返回,不执行定位;ST7920固定行起始地址映射
***********************************************************
*/
void Lcd12864_SetPos(unsigned char x, unsigned char y)
{
    unsigned char pos = 0;
    if(x < 1 || x > 4 || y < 1 || y > 8)
    {
        return;
    }
    y = y - 1;
    switch(x)
    {
        case 1 : pos = 0x80 + y; break;
        case 2 : pos = 0x90 + y; break;
        case 3 : pos = 0x88 + y; break;
        case 4 : pos = 0x98 + y; break;
        default : break;
    }
    Lcd12864_WriteCmd(pos);
}

/******************************************************************
* @brief     LCD12864写入GB2312汉字字符串(数组传参版)
* @param     cn:GB2312汉字字符串数组(双字节/汉字)
* @return    无
* @note      1. 调用前必须先调用Lcd12864_SetPos定位显示起始位置
*            2. 自动循环写入,直到检测到字符串结束符'\0'
*            3. 数组传参本质等价于指针
***********************************************************/
void Lcd12864_WriteCN( unsigned char cn[])  
{
        while(*cn)  
        {
                Lcd12864_WriteDat(*cn ++);  // 逐个写入数组元素,指针后移
        }
}




#ifndef __LCD12864_H__
#define __LCD12864_H__


#include        "config.h"

/**
***********************************************************
* @brief     LCD12864初始化函数(串口版)
* @param     无
* @return    无
* @note      纯中文显示适配,仅开启基础指令集,**PSB硬件接GND**
***********************************************************
*/
void Lcd12864_Init(void);   

/**
***********************************************************
* @brief     向LCD12864写入命令(串口版)
* @param     cmd:要写入的命令字(ST7920指令集,与并口一致)
* @return    无
* @note      写入前自动检测忙信号,确保LCD空闲后再操作
***********************************************************
*/
void Lcd12864_WriteCmd(unsigned char cmd);

/**
***********************************************************
* @brief     向LCD12864写入数据(串口版)
* @param     dat:要写入的8位数据(汉字双字节/ASCII字符)
* @return    无
* @note      写入前自动检测忙信号,适配GB2312和ASCII编码
***********************************************************
*/
void Lcd12864_WriteDat(unsigned char dat);

/**
***********************************************************
* @brief     LCD12864显示位置定位函数(无修改)
* @param     x:目标显示行号,有效范围1~4(LCD共4行)
* @param     y:目标显示列号,有效范围1~8(中文专属,1汉字占2列)
* @return    无
* @note      x/y越界时直接返回,不执行定位;ST7920固定行起始地址映射
***********************************************************
*/
void Lcd12864_SetPos(unsigned char x, unsigned char y);

/******************************************************************
* @brief     LCD12864写入GB2312汉字字符串(数组传参版)
* @param     cn:GB2312汉字字符串数组(双字节/汉字)
* @return    无
* @note      1. 调用前必须先调用Lcd12864_SetPos定位显示起始位置
*            2. 自动循环写入,直到检测到字符串结束符'\0'
*            3. 数组传参本质等价于指针
***********************************************************/
void Lcd12864_WriteCN( unsigned char cn[]) ;







#endif





#include "config.h"
#include        "USART.h"
#include        "GPIO.h"
#include        "timer.h"


/******************** IO配置函数 **************************/
void        GPIO_config(void)
{
        GPIO_InitTypeDef        GPIO_InitStructure;                //结构定义
//  P1口定义  485使能引脚
        GPIO_InitStructure.Pin  = GPIO_Pin_2;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作GPIO_Pin_All
        GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);        //初始化
        

        GPIO_InitStructure.Pin  = GPIO_Pin_All;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作GPIO_Pin_All
        GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P0,&GPIO_InitStructure);        //初始化
        
        //P3口定义  LCD12864        
        GPIO_InitStructure.Pin  = GPIO_Pin_2;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
        GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);        //初始化
        
        GPIO_InitStructure.Pin  = GPIO_Pin_3;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
        GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);        //初始化
        
        GPIO_InitStructure.Pin  = GPIO_Pin_4;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
        GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);        //初始化
        
        GPIO_InitStructure.Pin  = GPIO_Pin_5;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
        GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);        //初始化
        
        
}


/************************ 定时器配置 ****************************/
void        Timer_config(void)
{
        
//初值为1000时,为1ms定时器        
        TIM_InitTypeDef                TIM_InitStructure;                                        //结构定义
        TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;        //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
        TIM_InitStructure.TIM_Polity    = PolityLow;                        //指定中断优先级, PolityHigh,PolityLow
        TIM_InitStructure.TIM_Interrupt = ENABLE;                                //中断是否允许,   ENABLE或DISABLE
        TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                        //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
        TIM_InitStructure.TIM_ClkOut    = ENABLE;                                //是否输出高速脉冲, ENABLE或DISABLE
        TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000);                //初值, 1/2 = 0.5KHZ = 500HZ
        TIM_InitStructure.TIM_Run       = ENABLE;                                //是否初始化后启动定时器, ENABLE或DISABLE
        Timer_Inilize(Timer0,&TIM_InitStructure);                                //初始化Timer0          Timer0,Timer1,Timer2

////初值为1000时,为1ms定时器
//        TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;        //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
//        TIM_InitStructure.TIM_Polity    = PolityLow;                        //指定中断优先级, PolityHigh,PolityLow
//        TIM_InitStructure.TIM_Interrupt = ENABLE;                                //中断是否允许,   ENABLE或DISABLE
//        TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                        //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
//        TIM_InitStructure.TIM_ClkOut    = ENABLE;                                //是否输出高速脉冲, ENABLE或DISABLE
//        TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000);                //初值, 1/2 = 0.5KHZ = 500HZ
//        TIM_InitStructure.TIM_Run       = ENABLE;                                //是否初始化后启动定时器, ENABLE或DISABLE
//        Timer_Inilize(Timer1,&TIM_InitStructure);                                //初始化Timer1          Timer0,Timer1,Timer2

////初值为50时,为20ms定时器
//        TIM_InitStructure.TIM_Interrupt = ENABLE;                                //中断是否允许,   ENABLE或DISABLE. (注意: Timer2固定为16位自动重装, 中断固定为低优先级)
//        TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_12T;                //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
//        TIM_InitStructure.TIM_ClkOut    = ENABLE;                                //是否输出高速脉冲, ENABLE或DISABLE
//        TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / (50*12));                //初值 0.5/2=0.025KHZ = 25HZ
//        TIM_InitStructure.TIM_Run       = ENABLE;                                //是否初始化后启动定时器, ENABLE或DISABLE
//        Timer_Inilize(Timer2,&TIM_InitStructure);                                //初始化Timer2          Timer0,Timer1,Timer2
}














/*************  外部函数和变量声明 *****************/

void        UART_config(void)
{
        COMx_InitDefine                COMx_InitStructure;                                        //结构定义
        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;                //模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
        COMx_InitStructure.UART_BRT_Use   = BRT_Timer2;                        //使用波特率,   BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
        COMx_InitStructure.UART_BaudRate  = 9600ul;                        //波特率, 一般 110 ~ 115200
        COMx_InitStructure.UART_RxEnable  = ENABLE;                                //接收允许,   ENABLE或DISABLE
        COMx_InitStructure.BaudRateDouble = DISABLE;                        //波特率加倍, ENABLE或DISABLE
        COMx_InitStructure.UART_Interrupt = ENABLE;                                //中断允许,   ENABLE或DISABLE
        COMx_InitStructure.UART_Polity    = PolityLow;                        //中断优先级, PolityLow,PolityHigh
        COMx_InitStructure.UART_P_SW      = UART1_SW_P30_P31;        //切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)
        COMx_InitStructure.UART_RXD_TXD_Short = DISABLE;                //内部短路RXD与TXD, 做中继, ENABLE,DISABLE
        USART_Configuration(USART1, &COMx_InitStructure);                //初始化串口1 USART1,USART2

        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;                //模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
        COMx_InitStructure.UART_BaudRate  = 9600ul;                        //波特率,     110 ~ 115200
        COMx_InitStructure.UART_RxEnable  = ENABLE;                                //接收允许,   ENABLE或DISABLE
        COMx_InitStructure.UART_Interrupt = ENABLE;                                //中断允许,   ENABLE或DISABLE
        COMx_InitStructure.UART_Polity    = PolityLow;                        //中断优先级, PolityLow,PolityHigh
        COMx_InitStructure.UART_P_SW      = UART2_SW_P10_P11;        //切换端口,   UART2_SW_P10_P11,UART2_SW_P46_P47
        USART_Configuration(USART2, &COMx_InitStructure);                //初始化串口2 USART1,USART2

//        PrintString1("STC15F2K60S2 UART1 Test Prgramme!\r\n");        //SUART1发送一个字符串
        PrintString2("STC15F2K60S2 UART2 Test Prgramme!\r\n");        //SUART2发送一个字符串
}








#ifndef                __CONFIG_H
#define                __CONFIG_H


/*********************************************************/

#define MAIN_Fosc                22118400L        //定义主时钟
//#define MAIN_Fosc                12000000L        //定义主时钟
//#define MAIN_Fosc                11059200L        //定义主时钟
//#define MAIN_Fosc                 5529600L        //定义主时钟
//#define MAIN_Fosc                24000000L        //定义主时钟


/*********************************************************/

#include        "STC15Fxxxx.H"

void        UART_config(void);
void        GPIO_config(void);
void        Timer_config(void);

#endif















回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表