STM32 串口发送中文
一、汉字编码基础1.1、汉字识别UTF-8编码特点汉字通常占3个字节首字节特征1110xxxx(0xE0-0xEF)都 0x7F后续字节特征10xxxxxx(0x80-0xBF)都 0x7FGBK编码特点汉字占2个字节首字节特征0x81-0xFE都 0x7F第二字节特征0x40-0xFE除0x7F#include main.h #include string.h #define MAX_RX_BUFFER 64 // 全局变量 volatile uint8_t rx_buffer[MAX_RX_BUFFER]; volatile uint8_t rx_index 0; volatile uint8_t chinese_flag 0; volatile uint8_t chinese_bytes 0; // 判断是否为UTF-8汉字首字节 uint8_t is_utf8_chinese_start(uint8_t data) { return (data 0xE0 data 0xEF); // 1110xxxx } // 判断是否为UTF-8后续字节 uint8_t is_utf8_continuation(uint8_t data) { return (data 0x80 data 0xBF); // 10xxxxxx } // 判断是否为GBK汉字首字节 uint8_t is_gbk_chinese_start(uint8_t data) { return (data 0x81 data 0xFE); } // 判断是否为GBK汉字第二字节 uint8_t is_gbk_chinese_second(uint8_t data) { return (data 0x40 data 0xFE data ! 0x7F); } void Uart1_Init(void) { // 初始化代码同上... USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); } void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { uint8_t received_data USART_ReceiveData(USART1); // 处理汉字接收状态 if(chinese_flag 0) { // 正在接收汉字后续字节 rx_buffer[rx_index] received_data; chinese_flag--; if(chinese_flag 0) { // 汉字接收完成可以处理 printf(Received Chinese character: ); for(int i rx_index - chinese_bytes; i rx_index; i) { printf(%02X , rx_buffer[i]); } printf(\r\n); } } else if(is_utf8_chinese_start(received_data)) { // UTF-8汉字首字节 rx_buffer[rx_index] received_data; chinese_flag 2; // 还需要2个字节 chinese_bytes 3; // UTF-8汉字总字节数 } else if(is_gbk_chinese_start(received_data)) { // GBK汉字首字节 rx_buffer[rx_index] received_data; chinese_flag 1; // 还需要1个字节 chinese_bytes 2; // GBK汉字总字节数 } else { // 英文字符或其他 rx_buffer[rx_index] received_data; // 如果是换行或缓冲区满处理数据 if(received_data \n || rx_index MAX_RX_BUFFER-1) { rx_buffer[rx_index] \0; // 添加字符串结束符 process_received_data((uint8_t*)rx_buffer, rx_index); rx_index 0; } } USART_ClearITPendingBit(USART1, USART_IT_RXNE); } } // 处理接收到的数据 void process_received_data(uint8_t *data, uint8_t length) { printf(Received: ); for(int i 0; i length; i) { if(data[i] 0x20 data[i] 0x7E) { // 可打印ASCII字符 printf(%c, data[i]); } else { // 汉字字节或其他非打印字符 printf([%02X], data[i]); } } printf(\r\n); // 这里可以添加具体的汉字识别逻辑 detect_chinese_characters(data, length); } // 检测并识别汉字 void detect_chinese_characters(uint8_t *data, uint8_t length) { uint8_t i 0; while(i length) { // 检查UTF-8汉字 if(i 2 length is_utf8_chinese_start(data[i]) is_utf8_continuation(data[i1]) is_utf8_continuation(data[i2])) { printf(UTF-8 Chinese: %02X %02X %02X\r\n, data[i], data[i1], data[i2]); i 3; } // 检查GBK汉字 else if(i 1 length is_gbk_chinese_start(data[i]) is_gbk_chinese_second(data[i1])) { printf(GBK Chinese: %02X %02X\r\n, data[i], data[i1]); i 2; } else { // ASCII字符 if(data[i] 0x20 data[i] 0x7E) { printf(ASCII: %c\r\n, data[i]); } i; } } }其中ASCII检测data[i] 0x20 data[i] 0x7E判断0x20-0x7E32-126是因为ASCII成分构成 控制字符 (0x00-0x1F, 0x7F) 可打印ASCII字符 (0x20-0x7E) 扩展字符/多字节字符首字节 (0x80-0xFF)// 控制字符 (0x00-0x1F, 0x7F) // 可打印ASCII字符 (0x20-0x7E) // 扩展字符/多字节字符首字节 (0x80-0xFF) 0x7E: ~波浪线可打印字符 0x7F: DEL删除控制字符冲突区间分析UTF-8汉字首字节0xE0-0xEF(1110xxxx对应3字节UTF-8)GBK汉字首字节0x81-0xFE重叠区间0xE0-0xEF同时被两种编码识别为首字节。基于上下文自动检测// 改进的自动检测函数 uint8_t detect_encoding_type(uint8_t* data, uint8_t length) { // 统计编码特征 uint8_t utf8_score 0; uint8_t gbk_score 0; for(uint8_t i 0; i length; i) { if(data[i] 0xE0 data[i] 0xEF) { // 可能是UTF-8或GBK if(i 2 length) { // 检查UTF-8模式 if((data[i1] 0x80 data[i1] 0xBF) (data[i2] 0x80 data[i2] 0xBF)) { utf8_score 3; } // 检查GBK模式 if(i 1 length data[i1] 0x40 data[i1] 0xFE data[i1] ! 0x7F) { gbk_score 2; } } } else if(data[i] 0x81 data[i] 0xFE !(data[i] 0xE0 data[i] 0xEF)) { // 这是非重叠区的GBK首字节0x81-0xDF 和 0xF0-0xFE if(i 1 length data[i1] 0x40 data[i1] 0xFE data[i1] ! 0x7F) { gbk_score 2; } } } return (utf8_score gbk_score) ? ENCODING_UTF8 : ENCODING_GBK; }双缓冲区分处理// 分别用UTF-8和GBK方式尝试解析 void try_both_decodings(uint8_t *data, uint8_t length) { uint8_t i 0; while(i length) { // 尝试UTF-8 if(i 2 length data[i] 0xE0 data[i] 0xEF data[i1] 0x80 data[i1] 0xBF data[i2] 0x80 data[i2] 0xBF) { printf(Likely UTF-8: %02X %02X %02X\r\n, data[i], data[i1], data[i2]); i 3; } // 尝试GBK else if(i 1 length data[i] 0x81 data[i] 0xFE data[i1] 0x40 data[i1] 0xFE data[i1] ! 0x7F) { printf(Likely GBK: %02X %02X\r\n, data[i], data[i1]); i 2; } else { // ASCII if(data[i] 0x20 data[i] 0x7E) { printf(%c, data[i]); } i; } } }1.2、简单的汉字检测和响应// 简化的汉字处理 void simple_chinese_handler(void) { uint8_t i 0; while(i rx_index) { // 检测到汉字特征 if(rx_buffer[i] 0x7F) {// 快速过滤可能是多字节字符 // 再进一步判断具体类型 printf(Chinese character detected at position %d: , i); // 如果是GBK可能汉字 if(i 1 rx_index rx_buffer[i] 0x81) { printf(GBK: %02X%02X, rx_buffer[i], rx_buffer[i1]); i 2;// 跳过第二个字节 } // 如果是UTF-8可能汉字 else if(i 2 rx_index (rx_buffer[i] 0xF0) 0xE0) { printf(UTF-8: %02X%02X%02X, rx_buffer[i], rx_buffer[i1], rx_buffer[i2]); i 3;// 跳过第二、三个字节 } else { printf(其他多字节字符); i; } printf(\r\n); } else { // 肯定是单字节ASCII字符 // ASCII字符 if(rx_buffer[i] \r || rx_buffer[i] \n) { // 行结束 break; } i; } } }汉字检测if(data[i] 0x7F)判断大于0x7F1270x7E: ~波浪线可打印字符 0x7F: DEL删除控制字符。ASCII 编码范围:0x00 - 0x7F: 标准ASCII字符128个字符; 0x80 - 0xFF: 扩展ASCII区域判断if(rx_buffer[i] 0x7F)是用来检测可能的中文字符的,GBK编码特点 0x7F;UTF-8编码特点都 0x7F;实际上只判断 0x7F是不够精确的因为扩展ASCII字符0x80-0xFF也可能不是汉字;某些特殊符号也在 0x7F 范围内.if(rx_buffer[i] 0x7F)是一个快速筛选条件用于区分单字节ASCII和多字节字符; 初步判断可能是非ASCII字符如汉字;作为进一步精确判断的前提.
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2478981.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!