# 合泰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<
// 配置触摸控制寄存器
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
- 完整的初始化和控制序列
- 自定义字符生成
- 基本的图形显示功能