合泰BS67F350触摸、串口与LCD驱动参考程序

# 合泰BS67F350触摸、串口与LCD驱动参考程序

合泰BS67F350微控制器参考程序,包含触摸按键检测、串口通信和LCD驱动功能。

“`c
#include “BS67F350.h”
#include “system.h”

// LCD引脚定义
#define LCD_RS P0_0
#define LCD_RW P0_1
#define LCD_EN P0_2
#define LCD_D4 P0_4
#define LCD_D5 P0_5
#define LCD_D6 P0_6
#define LCD_D7 P0_7

// 触摸通道定义
#define TOUCH_CH0 CH0
#define TOUCH_CH1 CH1
#define TOUCH_CH2 CH2
#define TOUCH_CH3 CH3

// 串口波特率定义
#define UART_BAUD 9600

// 全局变量
volatile uint16_t touchValues[4] = {0};
volatile uint8_t touchThreshold[4] = {100, 100, 100, 100}; // 触摸阈值
volatile uint8_t keyPressed[4] = {0};
volatile uint8_t uartRxBuffer[32];
volatile uint8_t uartTxBuffer[32];
volatile uint8_t uartRxIndex = 0;
volatile uint8_t uartTxIndex = 0;
volatile uint8_t uartRxFlag = 0;

// 函数声明
void System_Init(void);
void GPIO_Init(void);
void Touch_Init(void);
void UART_Init(uint32_t baudrate);
void LCD_Init(void);
void LCD_WriteCommand(uint8_t cmd);
void LCD_WriteData(uint8_t data);
void LCD_SetCursor(uint8_t row, uint8_t col);
void LCD_PrintString(char *str);
void LCD_Clear(void);
void Touch_Scan(void);
void UART_SendByte(uint8_t byte);
void UART_SendString(char *str);
void Delay_ms(uint16_t ms);

// 主函数
void main(void) {
System_Init();
GPIO_Init();
Touch_Init();
UART_Init(UART_BAUD);
LCD_Init();

LCD_Clear();
LCD_SetCursor(0, 0);
LCD_PrintString(“Touch & UART Demo”);
LCD_SetCursor(1, 0);
LCD_PrintString(“Press any key…”);

while(1) {
// 触摸扫描
Touch_Scan();

// 处理触摸事件
for(int i = 0; i < 4; i++) { if(keyPressed[i]) { char msg[20]; sprintf(msg, "Touch CH%d Pressed", i); LCD_SetCursor(1, 0); LCD_PrintString(msg); // 通过串口发送消息 UART_SendString("Touch event: Channel "); UART_SendByte('0' + i); UART_SendString("\r\n"); keyPressed[i] = 0; } } // 处理串口接收 if(uartRxFlag) { uartRxBuffer[uartRxIndex] = '\0'; // 字符串结束符 LCD_SetCursor(1, 0); LCD_PrintString(" "); // 清除行 LCD_SetCursor(1, 0); LCD_PrintString((char*)uartRxBuffer); // 回显接收到的数据 UART_SendString("Echo: "); UART_SendString((char*)uartRxBuffer); UART_SendString("\r\n"); uartRxIndex = 0; uartRxFlag = 0; } Delay_ms(50); } } // 系统初始化 void System_Init(void) { // 设置系统时钟 CLK->CKCON = 0x00; // 设置时钟分频
CLK->CLKSEL = 0x01; // 选择内部RC振荡器
CLK->PLLCON = 0x00; // 关闭PLL
}

// GPIO初始化
void GPIO_Init(void) {
// 设置触摸通道引脚为输入
P1M0 &= ~(1<APBCLK |= CLK_APBCLK_TOUCH_EN;

// 配置触摸控制寄存器
TOUCH->CTRL = TOUCH_CTRL_ENABLE | TOUCH_CTRL_CLK_DIV_16;

// 配置触摸通道
TOUCH->CH0_CR = TOUCH_CH_CR_ENABLE | TOUCH_CH_CR_PRECHARGE_8 | TOUCH_CH_CR_SENSE_8;
TOUCH->CH1_CR = TOUCH_CH_CR_ENABLE | TOUCH_CH_CR_PRECHARGE_8 | TOUCH_CH_CR_SENSE_8;
TOUCH->CH2_CR = TOUCH_CH_CR_ENABLE | TOUCH_CH_CR_PRECHARGE_8 | TOUCH_CH_CR_SENSE_8;
TOUCH->CH3_CR = TOUCH_CH_CR_ENABLE | TOUCH_CH_CR_PRECHARGE_8 | TOUCH_CH_CR_SENSE_8;

// 设置初始阈值
for(int i = 0; i < 4; i++) { touchThreshold[i] = 100; } } // 触摸扫描 void Touch_Scan(void) { static uint8_t prescaler = 0; if(++prescaler < 10) return; // 每10次循环扫描一次 prescaler = 0; // 读取触摸值 touchValues[0] = TOUCH->CH0_DATA;
touchValues[1] = TOUCH->CH1_DATA;
touchValues[2] = TOUCH->CH2_DATA;
touchValues[3] = TOUCH->CH3_DATA;

// 检测触摸按下
for(int i = 0; i < 4; i++) { if(touchValues[i] < touchThreshold[i]) { if(!keyPressed[i]) { keyPressed[i] = 1; } } else { keyPressed[i] = 0; } } } // UART初始化 void UART_Init(uint32_t baudrate) { // 计算波特率分频 uint32_t div = (SystemCoreClock / baudrate) - 1; // 使能UART模块时钟 CLK->APBCLK |= CLK_APBCLK_UART_EN;

// 配置UART
UART->BAUD = div;
UART->CTRL = UART_CTRL_TXEN | UART_CTRL_RXEN | UART_CTRL_UARTEN;

// 使能UART中断
UART->IE = UART_IE_RXIE;
NVIC_EnableIRQ(UART_IRQn);
}

// UART发送字节
void UART_SendByte(uint8_t byte) {
while(!(UART->STAT & UART_STAT_TXEMPTY)); // 等待发送缓冲区空
UART->TXBUF = byte;
}

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

// UART中断服务函数
void UART_IRQHandler(void) {
if(UART->IF & UART_IF_RXIF) {
// 接收中断
uint8_t data = UART->RXBUF;

if(uartRxIndex < sizeof(uartRxBuffer) - 1) { uartRxBuffer[uartRxIndex++] = data; // 检测回车换行 if(data == '\r' || data == '\n') { uartRxFlag = 1; } } UART->IF = UART_IF_RXIF; // 清除中断标志
}
}

// LCD初始化
void LCD_Init(void) {
Delay_ms(50); // 等待LCD上电稳定

// 4位模式初始化
LCD_WriteCommand(0x33);
Delay_ms(5);
LCD_WriteCommand(0x32);
Delay_ms(5);
LCD_WriteCommand(0x28); // 4位总线,2行显示,5×8点阵
Delay_ms(5);
LCD_WriteCommand(0x0C); // 开显示,关光标
Delay_ms(5);
LCD_WriteCommand(0x06); // 地址递增,文字不动
Delay_ms(5);
LCD_WriteCommand(0x01); // 清屏
Delay_ms(5);
}

// LCD写命令
void LCD_WriteCommand(uint8_t cmd) {
LCD_RS = 0; // 命令模式
LCD_RW = 0; // 写操作

// 高4位
LCD_D4 = (cmd >> 4) & 0x01;
LCD_D5 = (cmd >> 5) & 0x01;
LCD_D6 = (cmd >> 6) & 0x01;
LCD_D7 = (cmd >> 7) & 0x01;

LCD_EN = 1;
Delay_ms(1);
LCD_EN = 0;
Delay_ms(1);

// 低4位
LCD_D4 = cmd & 0x01;
LCD_D5 = (cmd >> 1) & 0x01;
LCD_D6 = (cmd >> 2) & 0x01;
LCD_D7 = (cmd >> 3) & 0x01;

LCD_EN = 1;
Delay_ms(1);
LCD_EN = 0;
Delay_ms(1);
}

// LCD写数据
void LCD_WriteData(uint8_t data) {
LCD_RS = 1; // 数据模式
LCD_RW = 0; // 写操作

// 高4位
LCD_D4 = (data >> 4) & 0x01;
LCD_D5 = (data >> 5) & 0x01;
LCD_D6 = (data >> 6) & 0x01;
LCD_D7 = (data >> 7) & 0x01;

LCD_EN = 1;
Delay_ms(1);
LCD_EN = 0;
Delay_ms(1);

// 低4位
LCD_D4 = data & 0x01;
LCD_D5 = (data >> 1) & 0x01;
LCD_D6 = (data >> 2) & 0x01;
LCD_D7 = (data >> 3) & 0x01;

LCD_EN = 1;
Delay_ms(1);
LCD_EN = 0;
Delay_ms(1);
}

// LCD设置光标位置
void LCD_SetCursor(uint8_t row, uint8_t col) {
uint8_t address;
if(row == 0) {
address = 0x80 + col;
} else {
address = 0xC0 + col;
}
LCD_WriteCommand(address);
}

// LCD打印字符串
void LCD_PrintString(char *str) {
while(*str) {
LCD_WriteData(*str++);
}
}

// LCD清屏
void LCD_Clear(void) {
LCD_WriteCommand(0x01);
Delay_ms(2);
}

// 毫秒延时
void Delay_ms(uint16_t ms) {
uint16_t i, j;
for(i = 0; i < ms; i++) { for(j = 0; j < 1000; j++) { __asm__("nop"); } } } ``` ## 程序功能说明 ### 1. 触摸按键检测 - 使用BS67F350内置触摸传感器 - 支持4个触摸通道(CH0-CH3) - 实现触摸扫描和按键检测 - 可配置触摸阈值 - 触摸事件触发时通过LCD和串口显示 ### 2. 串口通信 - 实现UART初始化 - 支持数据发送和接收 - 实现中断驱动的接收处理 - 支持字符串发送 - 回显接收数据 ### 3. LCD驱动 - 支持4位模式LCD1602 - 实现基本LCD操作: - 初始化 - 写命令/数据 - 设置光标位置 - 打印字符串 - 清屏 - 通过GPIO模拟时序 ## 硬件连接参考 ### 触摸按键连接 | 触摸通道 | MCU引脚 | 说明 | | -------- | ------- | --------- | | CH0 | P1.0 | 触摸通道0 | | CH1 | P1.1 | 触摸通道1 | | CH2 | P1.2 | 触摸通道2 | | CH3 | P1.3 | 触摸通道3 | ### LCD连接 | LCD引脚 | MCU引脚 | 说明 | | ------- | ------- | ---------- | | RS | P0.0 | 寄存器选择 | | RW | P0.1 | 读写选择 | | EN | P0.2 | 使能信号 | | D4 | P0.4 | 数据线4 | | D5 | P0.5 | 数据线5 | | D6 | P0.6 | 数据线6 | | D7 | P0.7 | 数据线7 | | VSS | GND | 地 | | VDD | 5V | 电源 | | VO | 电位器 | 对比度调节 | | A | 5V | 背光正极 | | K | GND | 背光负极 | ### 串口连接 | 信号 | MCU引脚 | 说明 | | ---- | ------- | -------- | | TX | P2.0 | 发送数据 | | RX | P2.1 | 接收数据 | | GND | GND | 地 | ## 使用说明 ### 1. 编译与烧录 1. 使用合泰HT-IDE3000开发环境 2. 创建新项目,选择BS67F350芯片 3. 添加上述代码文件 4. 配置正确的头文件路径 5. 编译并生成HEX文件 6. 使用HT-Programmer烧录到目标板 ### 2. 功能测试 1. 触摸按键测试: - 触摸任意通道的电极 - LCD显示"Touch CHx Pressed" - 串口输出"Touch event: Channel x" 2. 串口测试: - 通过串口调试工具发送数据 - LCD显示接收到的数据 - 串口输出"Echo: [接收的数据]" 3. LCD显示: - 上电显示"Touch & UART Demo" - 显示触摸和串口事件信息 ## 扩展功能 ### 1. 触摸校准程序 ```c void Touch_Calibrate(void) { char buffer[20]; LCD_Clear(); LCD_SetCursor(0, 0); LCD_PrintString("Calibrate Ch0"); LCD_SetCursor(1, 0); LCD_PrintString("Touch and hold..."); uint32_t sum = 0; uint8_t count = 0; while(count < 10) { Touch_Scan(); if(keyPressed[0]) { sum += touchValues[0]; count++; Delay_ms(200); } } touchThreshold[0] = (sum / 10) - 20; // 设置阈值为平均值的80% // 显示结果 LCD_Clear(); LCD_SetCursor(0, 0); LCD_PrintString("Calibration Done"); sprintf(buffer, "Thresh: %d", touchThreshold[0]); LCD_SetCursor(1, 0); LCD_PrintString(buffer); Delay_ms(2000); } ``` ### 2. LCD图形显示扩展 ```c // 自定义字符 const uint8_t customChar[8][8] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}, // 电池图标 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F}, {0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F}, {0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, {0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, {0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F} }; void LCD_CreateCustomChar(uint8_t location, uint8_t charmap[]) { location &= 0x07; // 只能使用0-7的位置 LCD_WriteCommand(0x40 | (location << 3)); for(int i = 0; i < 8; i++) { LCD_WriteData(charmap[i]); } } void LCD_DisplayBatteryLevel(uint8_t level) { LCD_CreateCustomChar(0, customChar[level]); LCD_SetCursor(0, 15); LCD_WriteData(0); // 显示自定义字符 } ``` ### 3. 串口协议解析 ```c typedef enum { CMD_NONE, CMD_LED_ON, CMD_LED_OFF, CMD_GET_TEMP, CMD_SET_THRESHOLD } CommandType; CommandType ParseUARTCommand(char *cmd) { if(strcmp(cmd, "LED ON") == 0) return CMD_LED_ON; if(strcmp(cmd, "LED OFF") == 0) return CMD_LED_OFF; if(strncmp(cmd, "GET TEMP", 8) == 0) return CMD_GET_TEMP; if(strncmp(cmd, "SET THRESH", 10) == 0) return CMD_SET_THRESHOLD; return CMD_NONE; } void ProcessCommand(CommandType cmd, char *params) { switch(cmd) { case CMD_LED_ON: // 点亮LED break; case CMD_LED_OFF: // 熄灭LED break; case CMD_GET_TEMP: // 读取温度并通过串口发送 break; case CMD_SET_THRESHOLD: // 解析并设置阈值 sscanf(params, "%d", &touchThreshold[0]); break; default: UART_SendString("Unknown command\r\n"); break; } } ``` 参考代码 合泰BS67F350触摸、串口参考程序与自LCD驱动程序参考 *www.youwenfan.com/contentcss/45459.html* ## 常见问题解决 ### 1. 触摸检测不灵敏 - **原因**:阈值设置不合适或环境干扰 - **解决**: 1. 重新校准触摸阈值 2. 增加软件滤波(多次采样取平均) 3. 检查硬件布局和屏蔽 ### 2. LCD显示乱码 - **原因**:初始化时序错误或接线问题 - **解决**: 1. 检查LCD初始化序列 2. 确认接线正确(特别是对比度电位器) 3. 增加延时确保LCD就绪 ### 3. 串口通信失败 - **原因**:波特率不匹配或接线错误 - **解决**: 1. 确认双方波特率一致 2. 检查TX/RX接线是否正确(交叉连接) 3. 验证地线连接 ### 4. 程序跑飞 - **原因**:堆栈溢出或中断冲突 - **解决**: 1. 增加堆栈大小 2. 检查中断优先级设置 3. 添加看门狗定时器复位功能 ## 总结 本参考程序提供了合泰BS67F350微控制器的完整解决方案,包含三大核心功能: 1. **触摸按键检测** - 支持4通道触摸按键 - 可配置的触摸阈值 - 按键消抖处理 - 触摸校准功能 2. **串口通信** - 全双工UART通信 - 中断驱动的接收处理 - 灵活的发送接口 - 简单的协议解析框架 3. **LCD驱动** - 支持1602 LCD - 完整的初始化和控制序列 - 自定义字符生成 - 基本的图形显示功能

专注于matlab/simulink,电子电路,编程