STC15F100E单片机模拟串口

文章目录

一、芯片简介

STC15F100系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,新一代8051单片机,指令代码完全兼容传统8051,但是速度快6-12倍。

内部集成R/C时钟,5MHz~35MHz宽范围可设置,可以省掉外部晶振。

内部集成复位电路,可省掉外部复位电路。

6个通用I/O口,支持四种模式:准双向口/弱上拉、强推挽/强上拉、输入/高阻、开漏

芯片管脚图

二、开发环境

在Keil中添加STC芯片

  1. 下载STC-ISP软件

    https://www.stcmcudata.com/

  2. 打开STC-ISP软件,选择右侧"Keil仿真设置"栏

  3. 选择"添加型号和头文件到Keil中,添加STC仿真器驱动到Keil中", 选择Keil C51的安装目录

    例如:D:/software/keil4

  4. 系统会自动添加"STC"文件夹( C51/INC/ )

  5. Keil新建工程选择芯片型号时就会有新添加的STC芯片

三、软件模拟串口

STC15F100E芯片内部是不直接支持串口通信的,但是可以用I/O口+定时器来实现串口功能。

这里实现的是半双工通信

系统工作时钟为5.5296Mhz,波特率为9600bps。
引脚说明

  • P3.0为Uart的RX引脚
  • P3.1为Uart的TX引脚

原理说明

  • 发送原理

    设置定时器的定时时间为一个bit的的发送时间,在定时器中断服务函数中,设置Uart_TX引脚的值。
  • 接收原理

    将Uart_RX引脚设置为外部中断(下降沿触发)模式,捕获Uart接收的开始信号。
    设置第一次定时时间为 3 2 \frac{3}{2} 23个bit持续的时间,其余的定时时间为一个bit的持续时间,在定时器中断服务函数中对Uart_RX引脚进行采样。

程序

  • uart.c
c 复制代码
/*
module name :  uart
author      :  wkk
create time :  2023/12/5
*/

#include "uart.h"
/*
BaudRate -> timer
SysClk   : 5.5296Mhz
Baudrate : 115200
5_529_600 / 115200 = 48           ( x -> error )
5_529_600 / 9600   = 576
65536 - 48    = 65488  0xffd0
65536 - 48-24 = 65464  0xffb8

65536 - 576     = 64960  0xfdc0
65536 - 576-288 = 64672  0xfca0
*/

// define type u8
typedef unsigned char  u8;
// ext 2 3 4 register
// 7  6     5    4  3 2   1      0
// - ext4 ext3 ext2 - - tlclkO t0clkO
sfr int_clkO = 0x8f;

// 1T mode or /12
//   7     6   5  4    3     2   1 0
// t0x12 t1x12 - T2R T2_C/T T2x12 - -
sfr auxr = 0x8e;

// IE2
//  7  6   5   4   3   2   1    9
//  - ET4 ET3 ES4 ES3 ET2 ESP1 ES2
sfr ie2 = 0xaf;

// timer 
sfr TH2 = 0xd6;
sfr TL2 = 0xd7;

//define uart tx/rx port
sbit uart_rx = P3^0;       // P3.0 rx
sbit uart_tx = P3^1;       // P3.1 tx

u8 TEND,TING,tcnt,tbuf;
u8 REND,RING,rcnt,rbuf;

void Enable_Ext4(){
    int_clkO = int_clkO | 0x40;
}

void Disable_Ext4(){
    int_clkO = int_clkO & 0xbf;
}

void Timer2_config(){
    // 1T mode
    auxr = auxr & 0xf0;
    auxr = auxr | 0x04;
    // enable timer1 interrupt
    ie2 = ie2 | 0x04;
    // need to enable EA
}

void Timer2_Disable(){
    auxr = auxr & 0xef;
}

void Timer2_Enable(u8 th1,u8 tl1){
    TH2 = th1;
    TL2 = tl1;
    auxr = auxr | 0x10;
}

void Uart_Init(){
    //P3.0 work in interrupt mode ( int4 falling )
    Enable_Ext4();  
    // timer2 config 
    Timer2_config();
    Timer2_Disable();
    // need to enable EA
    
    TEND = 1;
    REND = 0;
    TING = 0;
    RING = 0;
    uart_tx = 1;
}

void Ext4_Interrupt() interrupt 16 {
    RING = 1;
    REND = 0;
    rcnt = 0;
    rbuf = 0;
    Timer2_Enable(0xfc,0xa0);
    Disable_Ext4();
}

void Uart_SendByte( u8 tx_data ) {
    tbuf = tx_data;
    tcnt = 0;
    TEND = 0;
    TING = 1;
    uart_tx = 0;
    Timer2_Enable(0xfd,0xc0);
    while( TEND != 1); // wait for tx complete!!
}

void Uart_LoopTest( ){
    if( TEND && REND == 1 ) {
        Uart_SendByte(rbuf);
        REND = 0;        
    }
}

void Timer2_Interrupt() interrupt 12  {
    if( RING ) {
        if( rcnt == 0 ) {
            Timer2_Disable();
            rbuf = rbuf >> 1;
            if( uart_rx ) rbuf = rbuf | 0x80;  
            Timer2_Enable(0xfd,0xc0);           
        }else if( rcnt == 8 ){
            Timer2_Disable();
            Enable_Ext4();
            RING = 0;
            REND = 1;
            // recv done !!!        
        }else {
            rbuf = rbuf >> 1;
            if( uart_rx ) rbuf = rbuf | 0x80;  
        } 
        rcnt ++;
    }else if( TING ) {
        if( tcnt == 8) {
            uart_tx = 1;
        }else if( tcnt == 9) {
            Timer2_Disable();
            TING = 0;
            TEND = 1;
            // tx done !!!   
        }else{
            uart_tx = tbuf & 0x01;
            tbuf = tbuf >> 1;
        }
        tcnt ++;
    }else{
        // other things
    }
}
  • uart.h
c 复制代码
#ifndef _UART_H_
#define _UART_H_
#include <reg51.h>

void Uart_Init(void);
void Uart_SendByte( unsigned char tx_data );
void Uart_LoopTest( void );
#endif
  • main.c
c 复制代码
#include <reg51.h>
#include "uart.h"

void Sys_Init(){
    Uart_Init();
    EA = 1;
}

void main(){
    Sys_Init();
    while(1) {
        //Uart_LoopTest();
    }
}

参考

相关推荐
代码游侠2 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
CODECOLLECT5 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen6 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠9 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_9 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技11 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计11 小时前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
小龙报12 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业12 小时前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能12 小时前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微