qq1152307078 发表于 2024-8-14 17:59:33

关于 8G1K08A-36I-SOP8 的P3.2模拟软件TX发送数据,P3.2没发正常进行发送

#include <STC8G.H>// 包含 STC8 系列单片机的头文件

// 定义引脚
sbit DAT_tx = P3^2;// 定义引脚 P3.2 为模拟数据线

// 定义协议常量
#define FOSC      11059200UL// 系统时钟频率
#define BAUD_RATE    115200   // 期望的波特率
#define BIT_TIME    (FOSC / (BAUD_RATE * 16)) // 每位的时间周期(16倍速)

#define TX_IDLE    0   // 空闲状态
#define TX_START   1   // 发送起始位状态
#define TX_DATA    2   // 发送数据位状态
#define TX_STOP    3   // 发送停止位状态

// 定义状态和缓冲区
bit busy;             // 发送状态标志
char tx_state;      // 当前发送状态
char tx_bit_count;    // 发送数据位计数
char tx_data;         // 待发送数据

// 定义需要发送的数据
const char tx_buffer[] = {0x55, 0x01, 0x01, 0xFF}; // 循环发送的数据
char tx_index = 0;    // 当前数据索引

// 定时器0中断服务程序
void Timer0_ISR() interrupt 1
{
    static unsigned char bit_time_count = 0;// 位时间计数器

    bit_time_count++;// 增加计数

    if (bit_time_count >= (BIT_TIME / 2))// 每位时间的一半
    {
      bit_time_count = 0;// 重置计数器

      switch (tx_state)
      {
            case TX_IDLE:
                if (busy)
                {
                  DAT_tx = 1;// 空闲状态,TX线为高电平
                }
                break;

            case TX_START:
                DAT_tx = 0;// 起始位,TX线为低电平
                tx_state = TX_DATA;// 切换到数据位状态
                tx_bit_count = 8;    // 数据位计数器设置为8位
                break;

            case TX_DATA:
                DAT_tx = (tx_data & 0x01) ? 1 : 0;// 发送数据位(最低有效位)
                tx_data >>= 1;// 右移数据,准备发送下一个位
                tx_bit_count--;// 数据位计数器递减
                if (tx_bit_count == 0)
                {
                  tx_state = TX_STOP;// 数据位发送完毕,切换到停止位状态
                }
                break;

            case TX_STOP:
                DAT_tx = 1;// 停止位,TX线为高电平
                tx_state = TX_IDLE;// 切换到空闲状态
                busy = 0;// 发送完成
                break;
      }
    }
}

void UartInit()
{
    // 配置定时器0为模式1(16位定时器)
    TMOD &= 0xF0;       // 清除定时器0的配置位
    TMOD |= 0x01;       // 设置定时器0为模式1
    TH0 = (65536 - (FOSC / (BAUD_RATE * 16))); // 计算定时器初值
    TL0 = TH0;          // 设置定时器低字节
    ET0 = 1;            // 使能定时器0中断
    TR0 = 1;            // 启动定时器0
    EA = 1;             // 开启全局中断

    tx_state = TX_IDLE; // 初始化状态为空闲状态
    busy = 0;         // 初始化为不忙碌
}

void UartSend(char dat)
{
    while (busy);// 等待发送完成
    busy = 1;      // 设置为忙碌状态
    tx_data = dat; // 设置待发送数据
    tx_state = TX_START; // 开始发送数据
}

void main()
{
    // 配置所有端口为标准模式
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    UartInit(); // 初始化UART

    while (1)
    {
      UartSend(tx_buffer); // 发送当前数据
      tx_index++; // 增加数据索引
      if (tx_index >= sizeof(tx_buffer)) // 如果索引超出数据缓冲区大小
      {
            tx_index = 0;// 重置索引以循环发送
      }
      while (busy);// 等待当前数据发送完成
    }
}


那位大神帮我看看是什么问题

soma 发表于 2024-8-14 18:09:46

模拟uart感觉有点丢包。要定义最小发送字节。

DebugLab 发表于 2024-8-14 18:55:17

有硬件UART为何没有使用,P31和P33有硬件UART的TXD
以前用15W104没有硬件串口,用例程的软件模拟串口正常

神农鼎 发表于 2024-8-14 21:35:40

8G1K08A-36I-SOP8,
P3.2是串口的接收,P3.3是串口的发送
软件模拟 串口通信 ? 不知道在想啥


Lkck8210 发表于 2024-8-15 11:31:04

本帖最后由 Lkck8210 于 2024-8-15 11:35 编辑

横竖你都是死等busy,直接用delay来生成波特率吧
void UartSend(uchar dat)
{
      uchar i=8;
      DAT_tx = 0;// 起始位
      Delay104us();//9600
      while(i--)
      {
                if(dat & 0x01)
                        DAT_tx = 1;
                else
                        DAT_tx = 0;
                dat>>=1;
                Delay104us();
      }
      DAT_tx = 1;// 停止位
      Delay104us();
}
页: [1]
查看完整版本: 关于 8G1K08A-36I-SOP8 的P3.2模拟软件TX发送数据,P3.2没发正常进行发送