WH9 发表于 2024-1-17 09:22:26

STC15F104W的串口是哪些引脚?

P3.0和P3.1可以做串口吗?

xxkj2010 发表于 2024-1-17 09:39:06

我记得只能用于下载,不能用于用户串口通讯。
不过准确的话,还得看一下手册 。

xxkj2010 发表于 2024-1-17 09:46:50



没有涉及到串口的内容

WH9 发表于 2024-1-17 09:55:44

xxkj2010 发表于 2024-1-17 09:46
没有涉及到串口的内容

谢谢,就是因为看手册上没有,才来问问看

乘风飞扬 发表于 2024-1-17 10:08:50

选型表里面可以看到,STC15F1xx系列芯片没有串口功能

xxkj2010 发表于 2024-1-17 10:30:18

这型号还没有定时器1呢,这点也得注意,我有一次就因此掉坑的。




泰勒soc 发表于 2024-1-17 10:59:53

15不是停产了吗

cnos 发表于 2024-1-17 11:09:02

2012年用STC15F104E做了一些485继电器控制小板,自己自制智能家居。

后面出了104W,就换了104W
后面又出了104WS,就自带串口了。

当时硬是用模拟串口做出来了,可以跑115200bps。






#include <reg52.h>                                                                                                                                //使用8052内核单片机
#include <intrins.h>                                                                                                                        //使用_nop_();
sbit IO1=P3^5;                                                                                                                                                //IO
sbit IO2=P3^4;                                                                                                                                                //IO
sbit IO3=P3^3;                                                                                                                                                //IO
sbit DE_RE=P3^2;                                                                                                                                        //智能家居485总线流控方向,1发送,0接收
sbit TX_IO=P3^1;                                                                                                                                        //模拟串口发送IO
sbit RX_IO=P3^0;                                                                                                                                        //模拟串口接收IO
sfr AUXR=0x8e;                                                                                                                                                //STC15F104E系列单片机特殊寄存器,控制定时器时钟来源频率
sfr P3M0=0xb2;                                                                                                                                                //P3IO口工作模式
sfr eeprom_data =0xc2;
sfr eeprom_addh =0xc3;
sfr eeprom_addl =0xc4;
sfr eeprom_cmd=0xc5;
sfr eeprom_star =0xc6;
sfr eeprom_cont =0xc7;

bit sending,receing,stpbsed,bytereceived;                                        //发送中,接收中,接收完毕标志
bit data_receive_enable;                                                                                //帧头判断成功,过零信号前一状态
bit trig_count_enable1;                                                                                                                //过零信号到达启动计时
bit trig_count_enable2;                                                                                                                //过零信号到达启动计时
bit traic_1_on,traic_2_on;
unsigned char rece_bit_count;                                                                                        //接收位计数变量
unsigned char rece_pls_count;                                                                                        //接收脉冲计数变量
unsigned char send_bit_count;                                                                                        //发送位计数变量
unsigned char send_pls_count;                                                                                        //发送脉冲计数变量
unsigned char receing_data;                                                                                                //正在接收着的临时数据
unsigned char byte_need_to_send;                                                                        //要发送出去的字节
unsigned char byte_received;                                                                                        //已收到的字节

unsigned char zhen_tou[]={0xFF,0x00,0x55,0xAA,0x00,0xFF};//帧头字串
unsigned char cast_tou[]={0xFF,0x00,0x55,0xAA,0xFF,0x00};//广播地址帧头

unsigned char jie_shou[]={0x00,0x00,0x00,0x00,0x00,0x00};//接收的数据帧

unsigned int code baud[]={0xa000,0xd000,0xe800,0xf400,0xfa00,0xfd00,0xfe00,0xff00,0xff25,0xff80,0xffc0};
                                                                                                //300-----600----1200---2400---4800---9600---14400--28800--33600--57600--115200
                                                                                                //smod=1@22.1184mhz,auxr|=0x80
unsigned char count,checksum,temp;                                                                //处理数据帧字节计数,校验和,临时传递变量
unsigned char etmp1,etmp2;                                                                                                //操作eeprom用的临时保存变量
unsigned char verify,fr_num;                                                                                        //帧头核对及数据帧接收位置
unsigned char com_bit_tick;                                                                                                //串口位节拍计时器,主要用作回包延时控制
unsigned char trig_count1;                                                                                                        //移相触发延时变量
unsigned char trig_count2;                                                                                                        //移相触发延时变量
unsigned char brightness1,brightness2;                                                //可控硅亮度
unsigned intbootdelay,baud_index;                                                                //启动延时,波特率索引值

//eeprom 命令:0空闲,1读字节,2写字节,3扇区擦除
//写到eeprom_cont 寄存器的值:0x81,小于24MHz
//eepROM 起始地址:0x0000,0x0000-0x01ff 第一扇区 0x0200-0x03ff第二扇区
void close_eeprom(void);
unsigned char read_eeprom(unsigned int addr);
void write_eeprom(unsigned int addr,dat);
void erase_eeprom(unsigned int addr);
void send_byte(unsigned char byte_will_send);                        //发送一个字节
unsigned char pack_ana(void);
void set_baud(unsigned char index);
void respond_packge(void);
void execute_cmd(void);
void byte_reced(void);
void traic_on_off(void);
void main(void)                                                                                                                                                //主程序
{                                                                                                                                                                                                        //开始
        unsigned long btn_push_count;
P3=0XCF;
AUXR=0xc0;                                                                                                                                                                //T0计时脉冲不分频,比传统8051快12倍
P3M0=0X3c;//00111100
TMOD=0X00;                                                                                                                                                                //16位自动重载模式,当TR0=0时向TH0,TL0写入数据将同时写入重载寄存器
TH0=0xfd;                                                                                                                                                                        //重载值=65536-(定时器脉冲频率÷波特率÷3)
TL0=0x00;                                                                                                                                                                        //溢出率=定时器脉冲频率÷(65536-重载值)
TH1=0xFB;
TL1=0xAE;                                                                                                                                                                        //50uS@22.1184mhz计数率
TR0=1;                                                                                                                                                                                //启动定时器,模拟串口开始工作
TR1=1;                                                                                                                                                                                //启动定时器,可控硅移相触发开始工作
EA=1;                                                                                                                                                                                        //打开总中断
ET0=1;                                                                                                                                                                                //打开定时器0中断
ET1=1;                                                                                                                                                                                //打开定时器1中断
PT0=1;                                                                                                                                                                                //优先保证定时器0中断,确保模拟串口的可靠性
DE_RE=0;
        bootdelay=15000;
        etmp1=35;
        while(--etmp1)
        {
        while(--bootdelay)
          {
                byte_reced();
                }
        }
        baud_index=read_eeprom(0x0001);
        set_baud(baud_index);
        zhen_tou=read_eeprom(0x0000);
        zhen_tou=~zhen_tou;
        brightness1=read_eeprom(0x0200);
        brightness2=read_eeprom(0x0201);
        traic_on_off();
while(1)                                                                                                                                                                        //主循环
{                                                                                                                                                                                                //主循环体开始
        byte_reced();
                if(TX_IO==0)
                {
                while(TX_IO==0)
                {
                        btn_push_count++;
                }
                if(btn_push_count>200000 && btn_push_count<500000){IO1=~IO1;}
                if(btn_push_count>500000 && btn_push_count<1500000){IO2=~IO2;}
                if(btn_push_count>1800000){IO3=~IO3;}
                btn_push_count=0;
    }
                //send_byte(0X55);
        }                                                                                                                                                                                                //主循环体结束
}                                                                                                                                                                                                        //主程序结束
void send_byte(unsigned char byte_will_send)                        //发送一个字节
{                                                                                                                                                                                                        //函数开始
byte_need_to_send=byte_will_send;                                                                        //传递要发送的数据
send_pls_count=3;                                                                                                                                        //采样倍率3
send_bit_count=8;                                                                                                                                        //8位数据一位停止
TX_IO=0;                                                                                                                                                                        //发送起始位
sending=1;                                                                                                                                                                //置标志位,中断程序开始发送该字节
stpbsed=0;
while(sending==1);                                                                                                                                                //等待数据发送完成
}                                                                                                                                                                                                        //函数结束
void timer0(void) interrupt 1                                                                                        //中断服务程序
{                                                                                                                                                                                                        //函数开始
//        IO3=!IO3;
if(receing)                                                                                                                                                                //接收中?
{                                                                                                                                                                                                //接收中开始
        if(--rece_pls_count==0)                                                                                                        //三次脉冲计数够了吗?
          {                                                                                                                                                                                        //接收一位二进制位开始
                rece_pls_count=3;                                                                                                                        //脉冲计数辅助变量复位
                if(rece_bit_count)                                                                                                                //是在接收数据位还是停止位
                  {                                                                                                                                                                                //接收数据位开始
                  receing_data=receing_data>>1;                                                                //向右移一位,准备拼入一位二进制数据
                  if(RX_IO==1){receing_data=receing_data|0x80;}//如果收到的是二进制位"1",则拼入最高位中
                  rece_bit_count=rece_bit_count-1;                                                //已接收一位,接收位计数变量计数
                  }                                                                                                                                                                                //接收数据位结束
                else                                                                                                                                                                        //如果已经收完8位数据
                  {                                                                                                                                                                                //就开始接收停止位
                        receing=0;                                                                                                                                        //本字节已接收完毕
                        if(RX_IO==1)                                                                                                                                //停止位是"1"吗
                          {                                                                                                                                                                        //是“1”
                                byte_received=receing_data;                                                                //将数据输出
                                bytereceived=1;
//------------------------------------------------//知道了……
                                }                                                                                                                                                                        //数据输出处理完毕
                        }                                                                                                                                                                                //停止位处理完毕
                }                                                                                                                                                                                        //接收一位二进制位结束
        }                                                                                                                                                                                                //接收中处理结束
else                                                                                                                                                                                        //还没收到停止位,不是正在接收状态
{                                                                                                                                                                                                //等待接收开始
    if(RX_IO==0)                                                                                                                                        //是一个起始位到来吗
    {                                                                                                                                                                                        //是.......
          receing=1;                                                                                                                                                //开始接收
          rece_pls_count=4;                                                                                                                        //置接收起始位脉冲数
          rece_bit_count=8;                                                                                                                        //置接收二进制位数
        }                                                                                                                                                                                        //起始位处理完毕
        }                                                                                                                                                                                                //等待接收完毕
//----------------------------------------------------------------------------------------
if(sending)                                                                                                                                                                //是正在发送状态吗
{                                                                                                                                                                                                //是……
        if(--send_pls_count==0)                                                                                                        //脉冲计数够了吗
          {                                                                                                                                                                                        //够了……
                send_pls_count=3;                                                                                                                        //脉冲计数复位
          if(send_bit_count)                                                                                                                //是在发送数据还是要发送停止位
          {                                                                                                                                                                                //发送数据开始
                  TX_IO=byte_need_to_send&0x01;                                                                //从最低位开始发送数据
                  byte_need_to_send=byte_need_to_send>>1;                        //移动数据准备下一次发送
                  send_bit_count=send_bit_count-1;                                                //已经发送了一位二进制数要记下来
                  }                                                                                                                                                                                //发送数据结束
          else                                                                                                                                                                        //数据已经发送完成
          {                                                                                                                                                                                //发送停止位开始
                        if(stpbsed)
                          {
                                sending=0;                                                                                                                                //放下旗帜表示数据已经发送完成
                                }
                  TX_IO=1;                                                                                                                                                //发送停止位
                        stpbsed=1;
                  }                                                                                                                                                                                //停止位发送完成
                }                                                                                                                                                                                        //一位二进制位处理完成
        }                                                                                                                                                                                                //发送状态处理完成
com_bit_tick--;                                                                                                                                                //串口位时间滴答向下
}                                                                                                                                                                                                        //中断函数结束
void timer1(void) interrupt 3                                                                                        //中断服务程序
{
if(IO3==0)                                                                                                                                                                //一个新的过零信号到来了吗
{
        trig_count_enable1=1;
        trig_count_enable2=1;
        }
if(traic_1_on==1)
{
        IO2=0;
        if(trig_count_enable1==1)
          {
                trig_count1++;
                if(trig_count1>=brightness1)
                  {
                        trig_count_enable1=0;
                        trig_count1=0;
                        IO2=1;
                        }
                }
        }
if(traic_2_on==1)
{
        IO1=0;
        if(trig_count_enable2==1)
          {
                trig_count2++;
                if(trig_count2>=brightness2)
                  {
                        trig_count_enable2=0;
                        trig_count2=0;
                        IO1=1;
                        }
                }
        }
}
unsigned char pack_ana(void)
{
        checksum=0;
        for(count=0;count<6;count++)
          {
                        checksum=checksum+zhen_tou;
                }
        for(count=0;count<5;count++)
          {
                        checksum=checksum+jie_shou;
                }
        if(checksum==jie_shou)
          {
                return(1);
                }
        else
          {
                return(0);
                }
        }
void set_baud(unsigned char index)
{
if(index>10)                                                                                                                                                        //faild value
        {
        index=5;
        }
        TR0=0;                                                                                                                                                                                //启动定时器,模拟串口开始工作
        TH0=baud/256;                                                                                                                        //重载值=65536-(定时器脉冲频率÷波特率÷3)
        TL0=baud%256;                                                                                                                        //溢出率=定时器脉冲频率÷(65536-重载值)
        TR0=1;                                                                                                                                                                                //启动定时器,模拟串口开始工作
        baud_index=index;
}
void respond_packge(void)
{
    com_bit_tick=100;
                while(com_bit_tick!=0);
                DE_RE=1;                                                                                                                                                                                                                //置75176为发送模式
                checksum=0;
                for(count=0;count<6;count++)
                  {
                        temp=zhen_tou;
                        send_byte(temp);
                        checksum=checksum+temp;
                        }
                for(count=0;count<5;count++)
                  {
                        checksum=checksum+jie_shou;
                        }
                jie_shou=checksum;
                for(count=0;count<6;count++)
                  {
                        send_byte(jie_shou);
                        }
                DE_RE=0;                                                                                                                                                                                                                //置75176为接收模式
}
void execute_cmd(void)
{
if(jie_shou==0x00)//断开继电器命令
          {
                if(jie_shou==0x00){IO1=0;}//关闭一号继电器
                if(jie_shou==0x01){IO2=0;}//关闭二号继电器
                if(jie_shou==0x02){IO3=0;}//关闭三号继电器
                if(jie_shou==0x01){respond_packge();}
                }
if(jie_shou==0x01)//接通继电器命令
          {
                if(jie_shou==0x00){IO1=1;}//闭合一号继电器
                if(jie_shou==0x01){IO2=1;}//闭合二号继电器
                if(jie_shou==0x02){IO3=1;}//闭合三号继电器
                if(jie_shou==0x01){respond_packge();}
                }
if(jie_shou==0x02)//查询继电器命令
          {
                if(jie_shou==0x00){if(IO1==1){jie_shou=0x01;}else{jie_shou=0x00;}}
                if(jie_shou==0x01){if(IO2==1){jie_shou=0x01;}else{jie_shou=0x00;}}
                if(jie_shou==0x02){if(IO3==1){jie_shou=0x01;}else{jie_shou=0x00;}}
                respond_packge();
                }
//---------------------
if(jie_shou==0x03)//设置可控硅1亮度命令
          {
                brightness1=200-jie_shou;
                traic_on_off();
                if(jie_shou==0x01){respond_packge();}
                }
if(jie_shou==0x04)//设置可控硅2亮度命令
          {
                brightness2=200-jie_shou;
                traic_on_off();
                if(jie_shou==0x01){respond_packge();}
                }
//---------------------
if(jie_shou==0x05)//设置并保存可控硅1亮度命令
          {
                IO1=IO2=traic_1_on=traic_2_on=0;
                brightness1=200-jie_shou;//计算亮度值
                etmp1=read_eeprom(0x0201);//读出第二通道可控硅亮度值进行保护
                erase_eeprom(0x0200);//擦除EEPROM
                write_eeprom(0x0200,brightness1);//写入新的第一通道可控硅值
                write_eeprom(0x0201,etmp1);//写回第二通道可控硅值
                traic_on_off();//判断是否启用可控硅控制
                if(jie_shou==0x01){respond_packge();}
                }
if(jie_shou==0x06)//设置并保存可控硅2亮度命令
          {
                IO1=IO2=traic_1_on=traic_2_on=0;
                brightness2=200-jie_shou;
                etmp1=read_eeprom(0x0200);//读出第一通道可控硅亮度值进行保护
                erase_eeprom(0x0200);//擦除EEPROM
                write_eeprom(0x0201,brightness2);//写入新的第二通道可控硅值
                write_eeprom(0x0200,etmp1);//写回第一通道可控硅值
                traic_on_off();//判断是否启用可控硅控制
                if(jie_shou==0x01){respond_packge();}
                }
//---------------------
if(jie_shou==0x10)//断开继电器命令,为了兼容485继电器模块的命令
          {
                IO1=0;
                if(jie_shou==0x01){respond_packge();}
                }
if(jie_shou==0x11)//接通继电器命令,为了兼容485继电器模块的命令
          {
                IO1=1;
                if(jie_shou==0x01){respond_packge();}
                }
if(jie_shou==0x12)//查询继电器命令,为了兼容485继电器模块的命令
          {
                if(IO1==1)
                  {
                        jie_shou=0x01;
                        }
                else
                  {
                        jie_shou=0x00;
                        }
                respond_packge();
                }
//---------------------
        if(jie_shou==0x15)//查询从机地址
          {
                jie_shou=read_eeprom(0x0000);
                jie_shou=~jie_shou;
                respond_packge();
                }
        if(jie_shou==0x16)//修改从机地址
          {
                etmp2=read_eeprom(0x0001);
                erase_eeprom(0x0000);
                write_eeprom(0x0000,jie_shou);
                write_eeprom(0x0001,etmp2);
                zhen_tou=jie_shou;
                zhen_tou=~jie_shou;
                if(jie_shou==0x01){respond_packge();}
                }
        if(jie_shou==0x18)//查询从机波特率
          {
                jie_shou=read_eeprom(0x0001);
                if(jie_shou>10)
                  {
                        jie_shou=5;
                        }
                respond_packge();
                }
        if(jie_shou==0x17)//设置从机波特率
          {
                if(jie_shou>10)
                  {
                        jie_shou=5;
                        }
                etmp1=read_eeprom(0x0000);
                erase_eeprom(0x0000);
                write_eeprom(0x0000,etmp1);
                write_eeprom(0x0001,jie_shou);
                set_baud(jie_shou);
                if(jie_shou==0x01){respond_packge();}
                }
}
void close_eeprom(void)
{
        eeprom_cont=0;
        eeprom_cmd=0;
        eeprom_star=0;
        eeprom_addh=0x80;
        eeprom_addl=0x00;
        }
unsigned char read_eeprom(unsigned int addr)
{
        unsigned char dat;
        eeprom_cont=0x81;
        eeprom_cmd=1;
        eeprom_addl=addr&0xff;
        eeprom_addh=addr>>8;
        eeprom_star=0x5a;
        eeprom_star=0xa5;
        _nop_();
        _nop_();
        _nop_();
        dat=eeprom_data;
        close_eeprom();
        return(dat);
        }
void write_eeprom(unsigned int addr,dat)
{
        eeprom_cont=0x81;
        eeprom_cmd=2;
        eeprom_addl=addr&0xff;
        eeprom_addh=addr>>8;
        eeprom_data=dat;
        eeprom_star=0x5a;
        eeprom_star=0xa5;
        _nop_();
        _nop_();
        _nop_();
        close_eeprom();
        }
void erase_eeprom(unsigned int addr)
{
        eeprom_cont=0x81;
        eeprom_cmd=3;
        eeprom_addl=addr&0xff;
        eeprom_addh=addr>>8;
        eeprom_star=0x5a;
        eeprom_star=0xa5;
        _nop_();
        _nop_();
        _nop_();
        close_eeprom();
        }
void byte_reced(void)
{
        if(bytereceived==1)
          {
                bytereceived=0;
                if(data_receive_enable)
                  {
                        jie_shou=byte_received;
                        fr_num++;
                        if(fr_num>=6)
                          {
                                data_receive_enable=0;
                                fr_num=0;
                                if(pack_ana()==1)
                                  {
                                        execute_cmd();
                                        }
                                }
                        }
                else
                  {
                  if( (zhen_tou==byte_received) || (cast_tou==byte_received))
                  {
                          verify++;
                          if(verify>=6)
                          {
                                  data_receive_enable=1;
                                        verify=0;
                                  }
                          }
                  else
                  {
                          verify=0;
                          data_receive_enable=0;
                          if(zhen_tou==byte_received)
                          {
                                  verify=1;
                                  }
                          }
                        }
//------------------------------------------------//
    }
        }
void traic_on_off(void)
{
        if(brightness1>=200){brightness1=199;traic_1_on=0;}else{traic_1_on=1;}
        if(brightness2>=200){brightness2=199;traic_2_on=0;}else{traic_2_on=1;}
        if(traic_1_on==1 || traic_2_on==1){P3M0=0X36;}else{P3M0=0x3c;}
        }

神农鼎 发表于 2024-1-17 16:17:27

用RMB0.59的可以仿真的 STC8G1K08-36I-SOP8








最新数据手册下载
深圳国芯人工智能有限公司-产品_STC8G系列 (stcai.com)
页: [1]
查看完整版本: STC15F104W的串口是哪些引脚?