一、芯片简介
STC15F100系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,新一代8051单片机,指令代码完全兼容传统8051,但是速度快6-12倍。
内部集成R/C时钟,5MHz~35MHz宽范围可设置,可以省掉外部晶振。
内部集成复位电路,可省掉外部复位电路。
6个通用I/O口,支持四种模式:准双向口/弱上拉、强推挽/强上拉、输入/高阻、开漏
芯片管脚图
二、开发环境
在Keil中添加STC芯片
- 下载STC-ISP软件
https://www.stcmcudata.com/ - 打开STC-ISP软件,选择右侧"Keil仿真设置"栏
- 选择"添加型号和头文件到Keil中,添加STC仿真器驱动到Keil中", 选择Keil C51的安装目录
例如:D:/software/keil4 - 系统会自动添加"STC"文件夹( C51/INC/ )
- 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
/* 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
#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
#include <reg51.h> #include "uart.h" void Sys_Init(){ Uart_Init(); EA = 1; } void main(){ Sys_Init(); while(1) { //Uart_LoopTest(); } }
参考
- 右移/左移和标志位CY的关系