找回密码
 立即注册
查看: 90|回复: 14

STC8H1K08 请问如何模拟一个串口呢?

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-05-05 16:29:36
已绑定手机

3

主题

9

回帖

65

积分

注册会员

积分
65
发表于 5 天前 | 显示全部楼层 |阅读模式
STC8H1K08 有两个串口,都在使用

现在需要额外模拟一个串口
我按照AI给的教程写了代码,麻烦各位大佬看看,是不是有问题啊,我新手小白不太懂
  1. #include <STC8H.H>
  2. // ==================== 环形缓冲区通用定义 ====================
  3. #define BUFFER_SIZE 20
  4. // 模拟串口(UART3)缓冲区
  5. unsigned char rx_buffer3[BUFFER_SIZE];
  6. unsigned char rx_in3 = 0;
  7. unsigned char rx_out3 = 0;
  8. unsigned char rx_count3 = 0;
  9. // 接收状态机
  10. unsigned char soft_rx_state = 0;    // 0:空闲, 1:起始位, 2:数据位, 3:停止位
  11. unsigned char soft_rx_byte = 0;     // 接收到的字节暂存
  12. unsigned char soft_rx_bit_cnt = 0;  // 数据位计数
  13. unsigned char soft_rx_stop_bit = 0; // 停止位标志
  14. // ==================== 模拟串口相关变量 ====================
  15. sbit SOFT_TXD = P3^6;   // 发送引脚
  16. sbit SOFT_RXD = P3^7;   // 接收引脚
  17. #define BIT_TIME_RELOAD_H 0xF1 // 示例值,需根据实际调试微调
  18. #define BIT_TIME_RELOAD_L 0x9A
  19. // ==================== 模拟串口初始化(P3.6 TXD, P3.7 RXD) ====================
  20. void SoftUart_Init(void) {
  21.                  // 引脚配置
  22.     P3M0 &= ~0xC0;
  23.     P3M1 &= ~0xC0;
  24.     P3M0 |= 0x40;   // P3.6 推挽输出 (TXD)
  25.     P3M1 |= 0x80;   // P3.7 高阻输入 (RXD)
  26.     SOFT_TXD = 1;
  27.     // 定时器0配置 (16-bit自动重载,3倍采样)
  28.     TMOD &= 0xF0;   // 清除T0模式位
  29.     TMOD |= 0x01;   // T0模式1: 16位(不可自动重载,在ISR中手动重载)
  30.     TL0 = BIT_TIME_RELOAD_L;
  31.     TH0 = BIT_TIME_RELOAD_H;
  32.     ET0 = 1;        // 使能定时器0中断
  33.     TR0 = 1;        // 启动定时器0
  34.     EA = 1;         // 确保总中断开通
  35.     soft_rx_state = 0;
  36. }
  37. // 重写SoftUart_SendByte使用BitDelay
  38. void SoftUart_SendByte(unsigned char dat) {
  39.     unsigned char i;
  40.     // 关闭定时器3中断,避免发送过程被接收中断干扰
  41.     IE2 &= ~0x20;
  42.     // 起始位
  43.     SOFT_TXD = 0;
  44.     BitDelay();
  45.     // 发送8个数据位(LSB first)
  46.     for (i = 0; i < 8; i++) {
  47.         if (dat & 0x01) SOFT_TXD = 1;
  48.         else SOFT_TXD = 0;
  49.         BitDelay();
  50.         dat >>= 1;
  51.     }
  52.     // 停止位
  53.     SOFT_TXD = 1;
  54.     BitDelay();
  55.     // 恢复定时器3中断
  56.     IE2 |= 0x20;
  57. }
  58. void Timer0_Isr(void) interrupt 1 {
  59.     // 手动重载定时器0(提升时序准确性)
  60.     TL0 = BIT_TIME_RELOAD_L;
  61.     TH0 = BIT_TIME_RELOAD_H;
  62.     switch (soft_rx_state) {
  63.         case 0: // 空闲,检测起始位
  64.             if (SOFT_RXD == 0) {
  65.                 soft_rx_state = 1;
  66.                 soft_rx_bit_cnt = 0;
  67.                 soft_rx_byte = 0;
  68.             }
  69.             break;
  70.         case 1: // 起始位确认(延迟半位中心)
  71.             soft_rx_state = 2;
  72.             break;
  73.         case 2: // 接收数据位(每次中断采集一位)
  74.             soft_rx_byte >>= 1;
  75.             if (SOFT_RXD) soft_rx_byte |= 0x80;
  76.             if (++soft_rx_bit_cnt >= 8) {
  77.                 soft_rx_state = 3;
  78.             }
  79.             break;
  80.         case 3: // 停止位校验
  81.             if (SOFT_RXD == 1) {
  82.                                                           P12 = ~P12;
  83.                 if (rx_count3 < BUFFER_SIZE) {
  84.                     rx_buffer3[rx_in3] = soft_rx_byte;
  85.                     rx_in3 = (rx_in3 + 1) % BUFFER_SIZE;
  86.                     rx_count3++;
  87.                 }
  88.             }
  89.             soft_rx_state = 0;
  90.             break;
  91.         default:
  92.             soft_rx_state = 0;
  93.     }
  94. }
  95. void main() {
  96.     P_SW2 |= 0x80;
  97.     SoftUart_Init();   // 初始化模拟串口
  98. P1M0 = 0x00;
  99.     P1M1 = 0x00;
  100. while(1) {
  101. if (rx_count3 > 0) {
  102.             unsigned char data3 = rx_buffer3[rx_out3];
  103.             SBUF = data3;
  104.             while(!TI);
  105.             TI = 0;
  106.             rx_out3 = (rx_out3 + 1) % BUFFER_SIZE;
  107.             rx_count3--;
  108.             //P12 = 1;
  109.             //Delay10ms();
  110.         }
  111. }
  112. }
复制代码







回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:401
  • 最近打卡:2026-05-08 09:46:24

850

主题

1万

回帖

2万

积分

管理员

积分
23212
发表于 5 天前 | 显示全部楼层
截图202605041343152185.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:401
  • 最近打卡:2026-05-08 09:46:24

850

主题

1万

回帖

2万

积分

管理员

积分
23212
发表于 5 天前 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:401
  • 最近打卡:2026-05-08 09:46:24

850

主题

1万

回帖

2万

积分

管理员

积分
23212
发表于 5 天前 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-05-05 16:29:36
已绑定手机

3

主题

9

回帖

65

积分

注册会员

积分
65
发表于 5 天前 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-05-05 16:29:36
已绑定手机

3

主题

9

回帖

65

积分

注册会员

积分
65
发表于 5 天前 | 显示全部楼层
神*** 发表于 2026-5-4 13:45
https://www.stcaimcu.com/data/download/Datasheet/STC32G.pdf

我是STC8H
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:543
  • 最近打卡:2026-05-07 10:27:33
已绑定手机

14

主题

239

回帖

2922

积分

金牌会员

积分
2922
发表于 5 天前 | 显示全部楼层
新手就换芯片吧,别折磨自己了。

不要过度依赖AI,看看官方例程。
截图202605041437181723.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2026-05-04 14:42:03

24

主题

108

回帖

926

积分

高级会员

积分
926
发表于 5 天前 | 显示全部楼层

你可以让一个串口,在不同的管脚上切换,比如读传感器数据,这个读的时刻你能掌握,就可以切换引脚,发读命令,读数据,而后回监听引脚,或者做日志发送,也可以切换发送,然后再换回监听,或者在引脚上用下降沿中断,触发本引脚的切换,这些都比你模拟的串口可靠.
我用printf输出调试信息,就是这样做的
  1. ////////////////////////////////////////
  2. // 重写printf字符发送重定向函数
  3. // 入口参数: dat (printf函数待打印的字符)
  4. // 函数返回: 需要返回入口参数的数据
  5. ////////////////////////////////////////
  6. char putchar (char dat) //将串口1和printf函数绑定
  7. {
  8.         unsigned int xdata t;
  9.   P_SW1 &= ~0xc0; //UART1/USART1: RxD(P3.0), TxD(P3.1)
  10.   TI=0;
  11.   SBUF=dat;
  12.         t=65535;
  13.   while (!TI && (t--)!=0);
  14.   TI=0;
  15.   P_SW1 = (P_SW1 & ~0xc0) | 0x40;                //UART1/USART1: RxD(P3.6), TxD(P3.7)
  16.   return dat;
  17. }
复制代码


回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-05-05 16:29:36
已绑定手机

3

主题

9

回帖

65

积分

注册会员

积分
65
发表于 5 天前 | 显示全部楼层
C_w*** 发表于 2026-5-4 14:37
新手就换芯片吧,别折磨自己了。

不要过度依赖AI,看看官方例程。

但是其他芯片贵嘛,我想着能省点钱
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-05-05 16:29:36
已绑定手机

3

主题

9

回帖

65

积分

注册会员

积分
65
发表于 5 天前 | 显示全部楼层
zh*** 发表于 2026-5-4 14:42
你可以让一个串口,在不同的管脚上切换,比如读传感器数据,这个读的时刻你能掌握,就可以切换引脚,发读命令, ...

这个更没玩过了
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-5-9 05:41 , Processed in 0.148430 second(s), 102 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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