|
|
本帖最后由 小橋流水不 于 2026-3-18 18:33 編輯
使用stc15f2k48s2單片機(jī),485接收溫濕度和風(fēng)速,如果把Task1_Run里的// if (currentTime - lastWindTime >= 1000)// {
// lastWindTime = currentTime;
// ModbusMasterSendWindData();
// windStep = 1;
// windStartTime = currentTime;
// printf("發(fā)送風(fēng)速請(qǐng)求...\n");
// }
}屏蔽,能收到溫濕度數(shù)據(jù),如果不屏蔽,只能收到風(fēng)速和風(fēng)力數(shù)據(jù)
ebd880824a66e78736e301a2a758291f.jpg (3.62 MB, 下載次數(shù): 0)
下載附件
2026-3-18 18:30 上傳
5cc10eb4e213afe7f37d3f5282df37c0.jpg (3.74 MB, 下載次數(shù): 0)
下載附件
2026-3-18 18:29 上傳
這是代碼:
#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"
/************* 功能說明 **************
雙串口全雙工中斷方式收發(fā)通訊程序。
串口1使用串口通訊,串口2使用RS485通訊
通過PC向MCU發(fā)送數(shù)據(jù), MCU收到后通過串口把收到的數(shù)據(jù)通過原路返回.
兩個(gè)串口同時(shí)使用定時(shí)器2做為波特率發(fā)生器,兩個(gè)串口的波特率相同,如果需要不同波特率,
需改變串口1配置定時(shí)器,串口2固定使用定時(shí)器2做為波特率發(fā)生器
串口1波特率:9600
串口2波特率:9600
開機(jī)lcd12864第一行顯示“風(fēng)速測(cè)量”
第二行顯示風(fēng)速:和風(fēng)速值
第三行顯示風(fēng)力:和風(fēng)力等級(jí)
采用rs485和風(fēng)速傳感器通訊,主機(jī)發(fā)送 01 03 00 00 00 02 C4 0B
“01”代表儀表地址。修改此地址可以和不同地址的儀表通信。
“03”modbus.功能碼,使用03“0000” 儀表內(nèi)部存器地址(即0x0000+0x01)
“0002”代表一次讀取2組數(shù)據(jù)
“C40B”CRC校驗(yàn),計(jì)算得到
此指令的意思是“用功能碼03讀取儀表地址為01的內(nèi)部寄存器地址01(即0x00+0x01)開始的2個(gè)單位的數(shù)據(jù)”
從機(jī)回復(fù):01 03 04 00 02 00 01 9A 33
說明:
“01”代表儀表地址
“03”代表modbus功能碼
“04”代表后面4字節(jié)為對(duì)應(yīng)儀表參數(shù)“0002”表示當(dāng)前風(fēng)速0x02=2,即0.02米/秒(默認(rèn)2位小數(shù)點(diǎn))
收到回復(fù)后將數(shù)值解析顯示在LCD12864上,也通過串口1打印到pc上
rs485采用串口2,波特率9600,串口發(fā)送接收控制引腳 :P12 在USART.h定義
******************************************/
xdata unsigned char str1[] = {"風(fēng)速:"};
xdata unsigned char str2[] = {"風(fēng)力: 級(jí)"};
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) //超時(shí)計(jì)數(shù)
// {
// if(--COM1.RX_TimeOut == 0)
// {
// if(COM1.RX_Cnt > 0)
// {
// for(i=0; i<COM1.RX_Cnt; i++)
// {
// TX1_write2buff(RX1_Buffer); //收到的數(shù)據(jù)通過串口1發(fā)送
// }
// }
// 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 風(fēng)速顯示函數(shù)
*/
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;
}
// 拆分四位數(shù)字(千/百/十/個(gè))
digit[0] = (speed / 1000) % 10;
digit[1] = (speed / 100) % 10;
digit[2] = (speed / 10) % 10;
digit[3] = speed % 10;
// 設(shè)置顯示位置
Lcd12864_SetPos(lcd_row, position);
// 顯示整數(shù)部分(處理前導(dǎo)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');
}
// 小數(shù)點(diǎn)+小數(shù)部分
Lcd12864_WriteDat('.');
Lcd12864_WriteDat(digit[2] + '0');
Lcd12864_WriteDat(digit[3] + '0');
// 單位
Lcd12864_WriteDat(' ');
Lcd12864_WriteDat('m');
Lcd12864_WriteDat('/');
Lcd12864_WriteDat('s');
}
/**
* @brief 風(fēng)級(jí)顯示函數(shù)
*/
void WindLevel_Display(u16 level, u8 row, u8 position)
{
xdata unsigned char digit[2] = {0};
u8 lcd_row = row;
// 風(fēng)級(jí)邊界處理(0~12級(jí))
if(level > 12)
{
Lcd12864_SetPos(lcd_row, position);
Lcd12864_WriteDat('-');
Lcd12864_WriteDat('-');
return;
}
// 拆分風(fēng)級(jí)數(shù)字
digit[0] = (level / 10) % 10; // 十位
digit[1] = level % 10; // 個(gè)位
Lcd12864_SetPos(lcd_row, position);
// 顯示風(fēng)級(jí)(處理前導(dǎo)0)
if(digit[0] == 0)
{
Lcd12864_WriteDat(' '); // 十位為0時(shí)顯示空格
}
else
{
Lcd12864_WriteDat(digit[0] + '0');
}
Lcd12864_WriteDat(digit[1] + '0');
}
/**
* @brief 溫度顯示函數(shù)
*/
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 濕度顯示函數(shù)
*/
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 任務(wù)1初始化
*/
void Task1_Init(void)
{
Lcd12864_WriteCmd(0x01); // 清屏
delay_ms(20);
// 顯示靜態(tài)文本
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 任務(wù)1運(yùn)行 - 修正版(雙獨(dú)立狀態(tài)機(jī))
*/
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;
// 風(fēng)速獨(dú)立狀態(tài)
static u8 windStep = 0; // 0:空閑, 1:等待響應(yīng)
static u32 windStartTime = 0;
// 溫濕度獨(dú)立狀態(tài)
static u8 tempStep = 0; // 0:空閑, 1:等待響應(yīng)
static u32 tempStartTime = 0;
u32 currentTime = GetSysTimeMs();
// ========== 風(fēng)速處理(獨(dú)立) ==========
if (windStep == 0)
{
// 空閑狀態(tài),檢查是否需要發(fā)送
if (currentTime - lastWindTime >= 1000)
{
lastWindTime = currentTime;
ModbusMasterSendWindData();
windStep = 1;
windStartTime = currentTime;
printf("發(fā)送風(fēng)速請(qǐng)求...\n");
}
}
else if (windStep == 1)
{
// 等待風(fēng)速響應(yīng)
ModbusMasterReceiveWind();
// 超時(shí)處理(500ms)
if (currentTime - windStartTime > 500)
{
printf("風(fēng)速響應(yīng)超時(shí)\n");
windStep = 0;
COM2.RX_Cnt = 0;
}
// 接收完成
else if (COM2.RX_TimeOut == 0 && COM2.RX_Cnt == 0)
{
windStep = 0;
}
}
// ========== 溫濕度處理(獨(dú)立) ==========
if (tempStep == 0)
{
// 空閑狀態(tài),檢查是否需要發(fā)送
if (currentTime - lastTempTime >= 3000)
{
lastTempTime = currentTime;
ModbusMasterSendTempHumiData();
tempStep = 1;
tempStartTime = currentTime;
printf("發(fā)送溫濕度請(qǐng)求...\n");
}
}
else if (tempStep == 1)
{
// 等待溫濕度響應(yīng)
ModbusMasterReceiveTempHumi();
// 超時(shí)處理(500ms)
if (currentTime - tempStartTime > 500)
{
printf("溫濕度響應(yīng)超時(shí)\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顯示(僅在數(shù)據(jù)變化時(shí))
if (windSpeed != lastWindSpeed || windLevel != lastWindLevel)
{
WindSpeed_Display(windSpeed, 1, 4);
WindLevel_Display(windLevel, 2, 4);
printf("LCD更新 - 風(fēng)速:%u(%.2f) 風(fēng)級(jí):%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[];
// 函數(shù)聲明
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}; // 溫濕度專用接收緩沖區(qū)
u16 windSpeed = 0;
u16 windLevel = 0;
int temp = 0; // 溫度,有符號(hào)整數(shù)
u16 humi = 0; // 濕度,無符號(hào)整數(shù)
/**
* @brief 清除接收緩沖區(qū)
*/
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 組裝風(fēng)速讀取指令(地址0x01)
*/
void ModbusMasterSetWindCmd(void)
{
u16 crc;
sendBuf[0] = SLAVE_ADDR_WIND; // 從機(jī)地址 0x01
sendBuf[1] = FUNC_READ_HOLD_REGS; // 功能碼 0x03
sendBuf[2] = 0x00; // 寄存器起始地址高字節(jié)
sendBuf[3] = REG_ADDR_START; // 寄存器起始地址低字節(jié) 0x00
sendBuf[4] = 0x00; // 寄存器數(shù)量高字節(jié)
sendBuf[5] = REG_COUNT_READ; // 寄存器數(shù)量低字節(jié) 0x02
crc = ModbusCRC16(sendBuf, 6);
sendBuf[6] = (u8)(crc & 0xFF); // CRC低字節(jié)
sendBuf[7] = (u8)(crc >> 8); // CRC高字節(jié)
}
/**
* @brief 發(fā)送風(fēng)速讀取指令
*/
void ModbusMasterSendWindData(void)
{
u8 i = 0;
ModbusMasterSetWindCmd();
printf("\n發(fā)送風(fēng)速指令: ");
for (i = 0; i < 8; i++)
{
TX2_write2buff(sendBuf);
printf("%bx ", sendBuf);
}
printf("\n");
}
/**
* @brief 接收并解析風(fēng)速/風(fēng)級(jí)
*/
void ModbusMasterReceiveWind(void)
{
u16 crc_calc;
u8 len;
u8 i;
if (COM2.RX_TimeOut == 0)
{
printf("風(fēng)速超時(shí),無數(shù)據(jù)\n");
return;
}
if (--COM2.RX_TimeOut == 0)
{
if (COM2.RX_Cnt > 0)
{
len = COM2.RX_Cnt;
printf("風(fēng)速原始數(shù)據(jù)(%d): ", len);
for(i=0; i<len; i++)
{
printf("%bx ", RX2_Buffer);
}
printf("\n");
// 檢查長度
if (len != 9)
{
printf("風(fēng)速長度錯(cuò)誤: %d, 期望9\n", len);
COM2.RX_Cnt = 0;
return;
}
// 復(fù)制數(shù)據(jù)
for(i=0; i<9; i++) receiveBuf = RX2_Buffer;
// 打印解析的數(shù)據(jù)
printf("解析: 地址=%bx, 功能碼=%bx, 長度=%bx, ",
receiveBuf[0], receiveBuf[1], receiveBuf[2]);
printf("數(shù)據(jù)=%bx%bx %bx%bx, CRC=%bx%bx\n",
receiveBuf[3], receiveBuf[4], receiveBuf[5], receiveBuf[6],
receiveBuf[7], receiveBuf[8]);
// 地址校驗(yàn)
if(receiveBuf[0] != SLAVE_ADDR_WIND)
{
printf("風(fēng)速地址錯(cuò)誤: 期望%bx, 收到%bx\n",
SLAVE_ADDR_WIND, receiveBuf[0]);
COM2.RX_Cnt = 0;
return;
}
// 功能碼校驗(yàn)
if(receiveBuf[1] != FUNC_READ_HOLD_REGS)
{
printf("風(fēng)速功能碼錯(cuò)誤\n");
COM2.RX_Cnt = 0;
return;
}
// CRC校驗(yàn)
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("風(fēng)速解析成功: %u (%.2f m/s), 風(fēng)級(jí): %u\n",
windSpeed, windSpeed * 0.01f, windLevel);
}
else
{
printf("風(fēng)速CRC錯(cuò)誤: 計(jì)算=%u, 收到=%bx%bx\n",
crc_calc, receiveBuf[8], receiveBuf[7]);
}
COM2.RX_Cnt = 0;
}
else
{
printf("風(fēng)速接收緩沖區(qū)為空\n");
}
}
}
/**
* @brief 組裝溫濕度讀取指令(地址0x02)
*/
void ModbusMasterSetTempHumiCmd(void)
{
u16 crc;
sendBuf[0] = SLAVE_ADDR_TEMP_HUMI; // 從機(jī)地址 0x02
sendBuf[1] = FUNC_READ_HOLD_REGS; // 功能碼 0x03
sendBuf[2] = 0x00; // 寄存器起始地址高字節(jié)
sendBuf[3] = REG_ADDR_START; // 寄存器起始地址低字節(jié) 0x00
sendBuf[4] = 0x00; // 寄存器數(shù)量高字節(jié)
sendBuf[5] = REG_COUNT_READ; // 寄存器數(shù)量低字節(jié) 0x02
crc = ModbusCRC16(sendBuf, 6);
sendBuf[6] = (u8)(crc & 0xFF); // CRC低字節(jié)
sendBuf[7] = (u8)(crc >> 8); // CRC高字節(jié)
}
/**
* @brief 發(fā)送溫濕度讀取指令
*/
void ModbusMasterSendTempHumiData(void)
{
u8 i = 0;
ModbusMasterSetTempHumiCmd();
printf("\n發(fā)送溫濕度指令: ");
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("收到溫濕度數(shù)據(jù)(%d字節(jié)): ", len);
for( i=0; i<len; i++) printf("%bX ", temp_humi_buf);
printf("\n");
// 校驗(yàn)數(shù)據(jù)長度
if (len != 9)
{
printf("溫濕度長度錯(cuò)誤: %d, 期望9字節(jié)\n", len);
COM2.RX_Cnt = 0;
return;
}
// 地址和功能碼校驗(yàn)
if (temp_humi_buf[0] != SLAVE_ADDR_TEMP_HUMI ||
temp_humi_buf[1] != FUNC_READ_HOLD_REGS)
{
printf("溫濕度地址/功能碼錯(cuò)誤: Addr=0x%bX, Func=0x%bX\n",
temp_humi_buf[0], temp_humi_buf[1]);
COM2.RX_Cnt = 0;
return;
}
// 數(shù)據(jù)長度校驗(yàn)
if (temp_humi_buf[2] != 0x04)
{
printf("溫濕度數(shù)據(jù)長度錯(cuò)誤: 0x%bX\n", temp_humi_buf[2]);
COM2.RX_Cnt = 0;
return;
}
// CRC校驗(yàn)
crc_calc = ModbusCRC16(temp_humi_buf, 7);
if (temp_humi_buf[7] == (u8)(crc_calc & 0xFF) &&
temp_humi_buf[8] == (u8)(crc_calc >> 8))
{
// 解析數(shù)據(jù):前兩個(gè)字節(jié)是濕度,后兩個(gè)字節(jié)是溫度
humi = (u16)temp_humi_buf[3] << 8 | temp_humi_buf[4];
raw_temp = (u16)temp_humi_buf[5] << 8 | temp_humi_buf[6];
// 溫度可能是帶符號(hào)的(如果傳感器支持負(fù)溫度)
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錯(cuò)誤! 計(jì)算: 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"
// 協(xié)議相關(guān)宏定義
#define SLAVE_ADDR_WIND 0x01 // 風(fēng)速傳感器地址
#define SLAVE_ADDR_TEMP_HUMI 0x02 // 溫濕度傳感器地址
#define FUNC_READ_HOLD_REGS 0x03 // 讀保持寄存器功能碼
#define REG_ADDR_START 0x00 // 寄存器起始地址
#define REG_COUNT_READ 0x02 // 要讀取的寄存器數(shù)量
// ==================== 全局變量聲明 ====================
extern u32 sendFreTime; // 串口發(fā)送數(shù)據(jù)間隔
extern u8 xdata sendBuf[8]; // 發(fā)送緩沖區(qū)
extern u8 xdata receiveBuf[9]; // 風(fēng)速接收緩沖區(qū)
extern u8 xdata temp_humi_buf[9]; // 溫濕度接收緩沖區(qū)
extern u16 windSpeed; // 風(fēng)速值 (單位: 0.01 m/s)
extern u16 windLevel; // 風(fēng)級(jí)值
extern int temp; // 溫度值 (單位: 0.1℃)
extern u16 humi; // 濕度值 (單位: 0.1%)
// ==================== 函數(shù)聲明 ====================
/**
* @brief 組裝風(fēng)速讀取指令
*/
void ModbusMasterSetWindCmd(void);
/**
* @brief 發(fā)送風(fēng)速讀取指令
*/
void ModbusMasterSendWindData(void);
/**
* @brief 接收并解析風(fēng)速/風(fēng)級(jí)
*/
void ModbusMasterReceiveWind(void);
/**
* @brief 組裝溫濕度讀取指令
*/
void ModbusMasterSetTempHumiCmd(void);
/**
* @brief 發(fā)送溫濕度讀取指令
*/
void ModbusMasterSendTempHumiData(void);
/**
* @brief 接收并解析溫濕度
*/
void ModbusMasterReceiveTempHumi(void);
/**
* @brief 清除接收緩沖區(qū)
*/
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]; //發(fā)送緩沖
u8 xdata RX1_Buffer[COM_RX1_Lenth]; //接收緩沖
u8 xdata TX2_Buffer[COM_TX2_Lenth]; //發(fā)送緩沖
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; //模式錯(cuò)誤
if(COMx->UART_Polity == PolityHigh) PS = 1; //高優(yōu)先級(jí)中斷
else PS = 0; //低優(yōu)先級(jí)中斷
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計(jì)算
if(j >= 65536UL) return 2; //錯(cuò)誤
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; //定時(shí)
INT_CLKO &= ~0x02; //不輸出時(shí)鐘
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); //定時(shí)
AUXR |= (1<<4); //Timer run enable
}
else return 2; //錯(cuò)誤
}
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); //內(nèi)部短路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; //高優(yōu)先級(jí)中斷
else IP2 &= ~1; //低優(yōu)先級(jí)中斷
if(COMx->UART_Mode == UART_9bit_BRTx) S2CON |= (1<<7); //9bit
else S2CON &= ~(1<<7); //8bit
j = (MAIN_Fosc / 4) / COMx->UART_BaudRate; //按1T計(jì)算
if(j >= 65536UL) return 2; //錯(cuò)誤
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; //模式錯(cuò)誤
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
}
}
/*************** 裝載串口發(fā)送緩沖 *******************************/
void TX1_write2buff(u8 dat) //寫入發(fā)送緩沖,指針+1
{
TX1_Buffer[COM1.TX_write] = dat; //裝發(fā)送緩沖
if(++COM1.TX_write >= COM_TX1_Lenth) COM1.TX_write = 0;
if(COM1.B_TX_busy == 0) //空閑
{
COM1.B_TX_busy = 1; //標(biāo)志忙
TI = 1; //觸發(fā)發(fā)送中斷
}
}
void TX2_write2buff(u8 dat) //寫入發(fā)送緩沖,指針+1
{
// 關(guān)鍵修改:只在發(fā)送第一個(gè)字節(jié)時(shí)切換485方向
if (COM2.B_TX_busy == 0) // 空閑狀態(tài),即將開始發(fā)送
{
RS485_DIR_PIN = RS485_TX_MODE; // 切到發(fā)送模式
delay_us(200); // 重要!延時(shí)等待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; //標(biāo)志忙
SET_TI2(); //觸發(fā)發(fā)送中斷
}
}
void PrintString1(u8 *puts)
{
for (; *puts != 0; puts++) TX1_write2buff(*puts); //遇到停止符0結(jié)束
}
void PrintString2(u8 *puts)
{
for (; *puts != 0; puts++) TX2_write2buff(*puts); //遇到停止符0結(jié)束
}
/*
void COMx_write2buff(COMx_Define *COMx, u8 dat) //寫入發(fā)送緩沖,指針+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結(jié)束
}
*/
/********************* UART1中斷函數(shù)************************/
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中斷函數(shù)************************/
void UART2_int (void) interrupt UART2_VECTOR
{
if(RI2) // 接收中斷
{
CLR_RI2();
// 收到數(shù)據(jù)時(shí),強(qiáng)制切回接收模式(確保模式正確)
RS485_DIR_PIN = RS485_RX_MODE;
if(COM2.B_RX_OK == 0)
{
if(COM2.RX_Cnt < COM_RX2_Lenth) // 防止緩沖區(qū)溢出
{
RX2_Buffer[COM2.RX_Cnt++] = S2BUF;
COM2.RX_TimeOut = TimeOutSet2;
}
else
{
// 緩沖區(qū)滿,清空
COM2.RX_Cnt = 0;
RX2_Buffer[COM2.RX_Cnt++] = S2BUF;
COM2.RX_TimeOut = TimeOutSet2;
}
}
}
if(TI2) // 發(fā)送中斷
{
CLR_TI2();
if(COM2.TX_read != COM2.TX_write)
{
// 還有數(shù)據(jù)要發(fā)送
S2BUF = TX2_Buffer[COM2.TX_read];
if(++COM2.TX_read >= COM_TX2_Lenth) COM2.TX_read = 0;
}
else
{
// 所有數(shù)據(jù)發(fā)送完畢
COM2.B_TX_busy = 0;
// 關(guān)鍵修改:延時(shí)等待最后1字節(jié)發(fā)送完成
// 波特率9600時(shí),1字節(jié)約1.04ms,延時(shí)1.5ms確保安全
delay_ms(2); // 2ms延時(shí),確保最后1字節(jié)完全發(fā)出
// 切換回接收模式
RS485_DIR_PIN = RS485_RX_MODE;
}
}
}
char putchar(char c)
{
if(c == '\n')
{
TX1_write2buff('\r');
}
TX1_write2buff((u8)c); // 對(duì)接硬件串口的發(fā)送緩沖,觸發(fā)中斷發(fā)送
return c; // 按C51標(biāo)準(zhǔn)要求返回,無實(shí)際意義
}
#ifndef __USART_H
#define __USART_H
#include "config.h"
// ********* 485方向控制定義 *********
#define RS485_DIR_PIN P12 // 485 DE/RE控制引腳(根據(jù)你的硬件修改)
#define RS485_TX_MODE 1 // 發(fā)送模式: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位數(shù)據(jù),可變波特率
#define UART_9bit (2<<6) //9位數(shù)據(jù),固定波特率
#define UART_9bit_BRTx (3<<6) //9位數(shù)據(jù),可變波特率
#define UART1_SW_P30_P31 0
#define UART1_SW_P36_P37 (1<<6)
#define UART1_SW_P16_P17 (2<<6) //必須使用內(nèi)部時(shí)鐘
#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; //串口號(hào)
u8 TX_read; //發(fā)送讀指針
u8 TX_write; //發(fā)送寫指針
u8 B_TX_busy; //忙標(biāo)志
u8 RX_Cnt; //接收字節(jié)計(jì)數(shù)
u8 RX_TimeOut; //接收超時(shí)
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; //多機(jī)通訊允許, ENABLE,DISABLE
u8 UART_RxEnable; //允許接收, ENABLE,DISABLE
u8 BaudRateDouble; //波特率加倍, ENABLE,DISABLE
u8 UART_Interrupt; //中斷控制, ENABLE,DISABLE
u8 UART_Polity; //優(yōu)先級(jí), PolityLow,PolityHigh
u8 UART_P_SW; //切換端口, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必須使用內(nèi)部時(shí)鐘)
u8 UART_RXD_TXD_Short; //內(nèi)部短路RXD與TXD, 做中繼, ENABLE,DISABLE
} COMx_InitDefine;
extern COMx_Define COM1,COM2;
extern u8 xdata TX1_Buffer[COM_TX1_Lenth]; //發(fā)送緩沖
extern u8 xdata RX1_Buffer[COM_RX1_Lenth]; //接收緩沖
extern u8 xdata TX2_Buffer[COM_TX2_Lenth]; //發(fā)送緩沖
extern u8 xdata RX2_Buffer[COM_RX2_Lenth]; //接收緩沖
u8 USART_Configuration(u8 UARTx, COMx_InitDefine *COMx);
void TX1_write2buff(u8 dat); //寫入發(fā)送緩沖,指針+1
void TX2_write2buff(u8 dat); //寫入發(fā)送緩沖,指針+1
void PrintString1(u8 *puts);
void PrintString2(u8 *puts);
//void COMx_write2buff(COMx_Define *COMx, u8 dat); //寫入發(fā)送緩沖,指針+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=無效 (對(duì)應(yīng)并行輸入的RS)
sbit SID = P3^3; // 串行數(shù)據(jù)端:收發(fā)數(shù)據(jù) (對(duì)應(yīng)并行輸入的RW)
sbit SCK = P3^4; // 串行時(shí)鐘端:上升沿鎖存數(shù)據(jù) (對(duì)應(yīng)并行輸入的E)
//sbit RST = P3^5; // 硬件復(fù)位端:0=復(fù)位,1=正常工作 (對(duì)應(yīng)并行輸入的RST)
// sbit PSB = P1^3; // 串口模式→硬件必須直接接GND,此引腳無效
/**
***********************************************************
* @brief 串行接收1字節(jié)數(shù)據(jù)(參考代碼適配,ST7920標(biāo)準(zhǔn))
* @return 拼接后的8位有效數(shù)據(jù)
* @note 連續(xù)讀2字節(jié),高4位+低4位拼接,適配ST7920串口讀數(shù)據(jù)時(shí)序
***********************************************************/
static unsigned char ReceiveByte(void)
{
unsigned char i, temp1, temp2;
temp1 = temp2 = 0;
// 讀高4位相關(guān)數(shù)據(jù)
for(i=0; i<8; i++)
{
temp1 = temp1 << 1;
SCK = 0;
SCK = 1;
SCK = 0;
if(SID) temp1++;
}
// 讀低4位相關(guān)數(shù)據(jù)
for(i=0; i<8; i++)
{
temp2 = temp2 << 1;
SCK = 0;
SCK = 1;
SCK = 0;
if(SID) temp2++;
}
return ((0xF0 & temp1) + (0x0F & temp2)); // 拼接為8位有效數(shù)據(jù)
}
/**
***********************************************************
* @brief 串行發(fā)送1字節(jié)數(shù)據(jù)(參考代碼核心,ST7920標(biāo)準(zhǔn)時(shí)序)
* @param dat:要發(fā)送的8位字節(jié)
* @note
***********************************************************/
static void Lcd_SendByte(unsigned char dat)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCK = 0; // 下降沿準(zhǔn)備數(shù)據(jù)
SID = (dat & 0x80) != 0; // 直接取最高位
dat = dat << 1;
SCK = 1; // 上升沿鎖存數(shù)據(jù)
SCK = 0; // 時(shí)鐘歸0,參考代碼標(biāo)準(zhǔn)操作
}
}
/**
***********************************************************
* @brief 檢測(cè)LCD12864忙信號(hào)(參考代碼適配,無卡死)
* @note 發(fā)0xFC讀忙前綴,循環(huán)判斷bit7,直到LCD空閑
***********************************************************/
void Lcd_12864_BusyCheck()
{
do
{
Lcd_SendByte(0xFC); // 串行讀忙前綴:11111 RW(1) RS(0) 0
}while(0x80 & ReceiveByte()); // bit7=1則忙,循環(huán)等待
}
/**
***********************************************************
* @brief 向LCD12864寫入命令(參考代碼核心,ST7920標(biāo)準(zhǔn))
* @param cmd:要寫入的命令字(ST7920指令集)
* @note CS片選→忙檢測(cè)→發(fā)前綴→高4位→低4位→CS失選,嚴(yán)格按手冊(cè)
***********************************************************/
void Lcd12864_WriteCmd(unsigned char cmd)
{
CS = 1; // 片選有效
Lcd_12864_BusyCheck(); // 忙檢測(cè),參考代碼邏輯無卡死
Lcd_SendByte(0xF8); // 串行寫命令固定前綴:11111 RW(0) RS(0) 0
Lcd_SendByte(0xF0 & cmd); // 發(fā)送命令高4位(屏蔽低4位)
Lcd_SendByte(0xF0 & (cmd << 4)); // 發(fā)送命令低4位(左移后屏蔽)
CS = 0; // 片選無效,完成命令寫入
delay_ms(1); // 短延時(shí),保證指令執(zhí)行
}
/**
***********************************************************
* @brief 向LCD12864寫入數(shù)據(jù)(參考代碼核心,ST7920標(biāo)準(zhǔn))
* @param dat:要寫入的8位數(shù)據(jù)(漢字雙字節(jié)/ASCII字符)
* @note 寫數(shù)據(jù)前綴0xFA,其余邏輯與寫命令一致
***********************************************************/
void Lcd12864_WriteDat(unsigned char dat)
{
CS = 1; // 片選有效
Lcd_12864_BusyCheck(); // 忙檢測(cè)
Lcd_SendByte(0xFA); // 串行寫數(shù)據(jù)固定前綴:11111 RW(0) RS(1) 0
Lcd_SendByte(0xF0 & dat); // 發(fā)送數(shù)據(jù)高4位
Lcd_SendByte(0xF0 & (dat << 4)); // 發(fā)送數(shù)據(jù)低4位
CS = 0; // 片選無效
delay_ms(1); // 短延時(shí),保證數(shù)據(jù)鎖存
}
/**
***********************************************************
* @brief LCD12864初始化函數(shù)(參考代碼標(biāo)準(zhǔn)串口流程,必顯!)
* @note 完全對(duì)齊參考代碼的初始化指令,復(fù)位+3次0x30+標(biāo)準(zhǔn)配置
***********************************************************/
void Lcd12864_Init(void)
{
// RST = 0;
// delay_ms(100); // 參考代碼用100ms延時(shí),保證硬件復(fù)位徹底
// RST = 1;
// delay_ms(100); // 復(fù)位后穩(wěn)定時(shí)間
// 參考代碼核心:連續(xù)3次發(fā)0x30,確保ST7920識(shí)別并進(jìn)入基礎(chǔ)指令集
Lcd12864_WriteCmd(0x30);
delay_ms(100);
Lcd12864_WriteCmd(0x30);
delay_ms(100);
Lcd12864_WriteCmd(0x30);
delay_ms(100);
// 參考代碼標(biāo)準(zhǔn)后續(xù)配置,按順序執(zhí)行
Lcd12864_WriteCmd(0x03); // 入口模式設(shè)置
delay_ms(50);
Lcd12864_WriteCmd(0x01); // 清屏
delay_ms(100);
Lcd12864_WriteCmd(0x06); // 光標(biāo)移動(dòng)方向配置
delay_ms(100);
Lcd12864_WriteCmd(0x0C); // 開顯示、關(guān)光標(biāo)、關(guān)閃爍
delay_ms(100);
}
// 以下2個(gè)函數(shù):完全保留你的代碼,無任何修改!!!
/**
***********************************************************
* @brief LCD12864顯示位置定位函數(shù)
* @param x:目標(biāo)顯示行號(hào),有效范圍1~4(LCD共4行)
* @param y:目標(biāo)顯示列號(hào),有效范圍1~8(中文專屬,1漢字占2列)
* @return 無
* @note x/y越界時(shí)直接返回,不執(zhí)行定位;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漢字字符串(數(shù)組傳參版)
* @param cn:GB2312漢字字符串?dāng)?shù)組(雙字節(jié)/漢字)
* @return 無
* @note 1. 調(diào)用前必須先調(diào)用Lcd12864_SetPos定位顯示起始位置
* 2. 自動(dòng)循環(huán)寫入,直到檢測(cè)到字符串結(jié)束符'\0'
* 3. 數(shù)組傳參本質(zhì)等價(jià)于指針
***********************************************************/
void Lcd12864_WriteCN( unsigned char cn[])
{
while(*cn)
{
Lcd12864_WriteDat(*cn ++); // 逐個(gè)寫入數(shù)組元素,指針后移
}
}
#ifndef __LCD12864_H__
#define __LCD12864_H__
#include "config.h"
/**
***********************************************************
* @brief LCD12864初始化函數(shù)(串口版)
* @param 無
* @return 無
* @note 純中文顯示適配,僅開啟基礎(chǔ)指令集,**PSB硬件接GND**
***********************************************************
*/
void Lcd12864_Init(void);
/**
***********************************************************
* @brief 向LCD12864寫入命令(串口版)
* @param cmd:要寫入的命令字(ST7920指令集,與并口一致)
* @return 無
* @note 寫入前自動(dòng)檢測(cè)忙信號(hào),確保LCD空閑后再操作
***********************************************************
*/
void Lcd12864_WriteCmd(unsigned char cmd);
/**
***********************************************************
* @brief 向LCD12864寫入數(shù)據(jù)(串口版)
* @param dat:要寫入的8位數(shù)據(jù)(漢字雙字節(jié)/ASCII字符)
* @return 無
* @note 寫入前自動(dòng)檢測(cè)忙信號(hào),適配GB2312和ASCII編碼
***********************************************************
*/
void Lcd12864_WriteDat(unsigned char dat);
/**
***********************************************************
* @brief LCD12864顯示位置定位函數(shù)(無修改)
* @param x:目標(biāo)顯示行號(hào),有效范圍1~4(LCD共4行)
* @param y:目標(biāo)顯示列號(hào),有效范圍1~8(中文專屬,1漢字占2列)
* @return 無
* @note x/y越界時(shí)直接返回,不執(zhí)行定位;ST7920固定行起始地址映射
***********************************************************
*/
void Lcd12864_SetPos(unsigned char x, unsigned char y);
/******************************************************************
* @brief LCD12864寫入GB2312漢字字符串(數(shù)組傳參版)
* @param cn:GB2312漢字字符串?dāng)?shù)組(雙字節(jié)/漢字)
* @return 無
* @note 1. 調(diào)用前必須先調(diào)用Lcd12864_SetPos定位顯示起始位置
* 2. 自動(dòng)循環(huán)寫入,直到檢測(cè)到字符串結(jié)束符'\0'
* 3. 數(shù)組傳參本質(zhì)等價(jià)于指針
***********************************************************/
void Lcd12864_WriteCN( unsigned char cn[]) ;
#endif
#include "config.h"
#include "USART.h"
#include "GPIO.h"
#include "timer.h"
/******************** IO配置函數(shù) **************************/
void GPIO_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //結(jié)構(gòu)定義
// 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); //初始化
}
/************************ 定時(shí)器配置 ****************************/
void Timer_config(void)
{
//初值為1000時(shí),為1ms定時(shí)器
TIM_InitTypeDef TIM_InitStructure; //結(jié)構(gòu)定義
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_Polity = PolityLow; //指定中斷優(yōu)先級(jí), PolityHigh,PolityLow
TIM_InitStructure.TIM_Interrupt = ENABLE; //中斷是否允許, ENABLE或DISABLE
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定時(shí)鐘源, 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; //是否初始化后啟動(dòng)定時(shí)器, ENABLE或DISABLE
Timer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2
////初值為1000時(shí),為1ms定時(shí)器
// TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
// TIM_InitStructure.TIM_Polity = PolityLow; //指定中斷優(yōu)先級(jí), PolityHigh,PolityLow
// TIM_InitStructure.TIM_Interrupt = ENABLE; //中斷是否允許, ENABLE或DISABLE
// TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定時(shí)鐘源, 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; //是否初始化后啟動(dòng)定時(shí)器, ENABLE或DISABLE
// Timer_Inilize(Timer1,&TIM_InitStructure); //初始化Timer1 Timer0,Timer1,Timer2
////初值為50時(shí),為20ms定時(shí)器
// TIM_InitStructure.TIM_Interrupt = ENABLE; //中斷是否允許, ENABLE或DISABLE. (注意: Timer2固定為16位自動(dòng)重裝, 中斷固定為低優(yōu)先級(jí))
// TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_12T; //指定時(shí)鐘源, 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; //是否初始化后啟動(dòng)定時(shí)器, ENABLE或DISABLE
// Timer_Inilize(Timer2,&TIM_InitStructure); //初始化Timer2 Timer0,Timer1,Timer2
}
/************* 外部函數(shù)和變量聲明 *****************/
void UART_config(void)
{
COMx_InitDefine COMx_InitStructure; //結(jié)構(gòu)定義
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; //中斷優(yōu)先級(jí), PolityLow,PolityHigh
COMx_InitStructure.UART_P_SW = UART1_SW_P30_P31; //切換端口, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必須使用內(nèi)部時(shí)鐘)
COMx_InitStructure.UART_RXD_TXD_Short = DISABLE; //內(nèi)部短路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; //中斷優(yōu)先級(jí), 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發(fā)送一個(gè)字符串
PrintString2("STC15F2K60S2 UART2 Test Prgramme!\r\n"); //SUART2發(fā)送一個(gè)字符串
}
#ifndef __CONFIG_H
#define __CONFIG_H
/*********************************************************/
#define MAIN_Fosc 22118400L //定義主時(shí)鐘
//#define MAIN_Fosc 12000000L //定義主時(shí)鐘
//#define MAIN_Fosc 11059200L //定義主時(shí)鐘
//#define MAIN_Fosc 5529600L //定義主時(shí)鐘
//#define MAIN_Fosc 24000000L //定義主時(shí)鐘
/*********************************************************/
#include "STC15Fxxxx.H"
void UART_config(void);
void GPIO_config(void);
void Timer_config(void);
#endif
|
|