STC15 MCU 串口编程 proteus 仿真 SDCC51
1.STC单片机接口比传统的51单片机多得多,学起来更有意思。据说这种单片机得实际使用也很多,价格便宜,可以用来DIY。
2.KEIL是比较流行的编程工具,有点大,还需要license之类的,对于业余爱好用SDCC51也不错,更简洁。
3.proteus8.9中只有一个STC15单片机,先在网上找一些STC的资料
4.现代的单片机集成度高,一般不再外扩数据总线,串口用的比较多,类型也多。
5.STC15的串口和传统51兼容,但是proteus仿真还有些问题。
电路图如下,时钟复位都可选内置,proteus好像也不能仿真外置晶振和复位,干脆不画了。用虚拟示波器和虚拟终端配合调试。
双击MCU,在编辑固件中选用 之前已经下载安装好的SDCC51 自动创建程序框架,只需要改写一个main.c文件,proteus可以控制编译,仿真,源程序级调试,变量和寄存器观察,很方便。
1.对比了串口传统配置方式和STC15专用配置
2.新增寄存器的使用方法
3.SPI发送
4.SDCC51内嵌汇编的使用
/* Main.c file generated by New Project wizard * * Created: 2023-1-2 * Processor: STC15W4K32S4 * Compiler: SDCC for 8051 */ #include <mcs51reg.h> #define sfr __sfr #define idata __idata #define xdata __xdata #define interrupt __interrupt #define using __using #define MAIN_Fosc 11059200L #define Baudrate1 9600L //SDCC51 特殊寄存器的定义方式 __sbit __at 0x97 LED_P1_7 ; //P1_7 __sfr __at 0x8E AUXR ; //T0x12, T1x12, Uart M0x6, T2R __sfr __at 0x8F AUXR2 ; //T0x12, T1x12, Uart M0x6, T2R __sfr __at 0xA2 AUXR1 ; //s1[2], cpp[2], spi[2], 0,DPS __sfr __at 0xA2 P_SW1 ; __sfr __at 0xAF IE2 ; __sfr __at 0xCD SPSTAT ; //spif, wcol, [6] __sfr __at 0xCE SPCTL ; //ssig, spen, dord, mstr, cpol, cpha, spr1, spr0 __sfr __at 0xCF SPDAT ; __sfr __at 0xD6 T2H ; __sfr __at 0xD7 T2L ; unsigned char xdata * pdata1; unsigned char xdata xdata2[10]; unsigned char xdata * p8255; int i=0; char rxc; __bit flag = 0; __bit flag_send = 0; void timer0(void) interrupt 1 using 1 { EA =0; flag = !flag; if(flag) { //P1_7=0; LED_P1_7 = 0; i=0; } else { //P1_7=1; LED_P1_7 = 1; } //TH0=0xff; // STC15 mode 0 auto load //TL0=0x16; EA =1; } void timer2(void) interrupt 12 using 1 { EA =0; EA =1; } void int1(void) interrupt 2 using 2 { EA =0; SBUF = 'W'; while(TI==0); TI=0; EA =1; } void serial(void) interrupt 4 using 3 { ES =0; if(RI) { rxc = SBUF; RI=0; SBUF = rxc; flag_send = 1; } if(TI) { TI=0; flag_send = 0; } ES =1; }
void send(char c) { while(flag_send); flag_send = 1; SBUF = c; } void sendstring(char* s) { while(*s) { send(*s++); } } void delay(int k) { int i; if(k< 0) return; for(i=0; i<k; i++); } //SDCC51 内嵌汇编的写法 void test_asm(void) { __asm ; This is a comment label: nop nop push acc push b push dpl push dph push psw mov acc, #0b11001100 mov psw,#0x00 inc acc pop psw pop dph pop dpl pop b pop acc __endasm; } void t0_init() { TMOD &= 0b11111100; TH0=0xff; // +1 TL0=0x80; TR0=1; //T0 start ET0 =1; //enable T0 int } void t2_init() { TMOD |= 0b00000001; // 0010 0010 T1,8bit auto timer, T0 16bit timer TMOD &= 0b11111101; AUXR |= 0b00010101; // T2 不分频 做 串口定时器 AUXR &= 0b11110111; //T2为定时器 AUXR2 &= 0b11111011; //禁止T2OUT IE2 &= 0b11111011; //禁止T2中断 TH2=0xff; // +1 TL2=0x80; //TR0=1; //T0 start //ET0 =1; //enable T0 int } void eint0_init() { IT1 = 1; // 1 -> 0 EX1=1; //enable int1 } //传统的8bit 配置方法,连续发送和中断收发都稳定,但是波特率高8倍 //新16bit法,中断收发不稳定,可能是仿真模型的问题,也可能配置还没弄对 void uart_init() { P_SW1 = P_SW1 & 0b00111111; // uart用P3口 #if 1 //传统的8bit 自动装载模式似乎速度8倍 AUXR &= 0b10111111; //传统模式 12分频 TMOD |= 0b00100000; // 0010 0010 T1,8bit auto timer, TMOD &= 0b11101111; SCON = 0X50; // 0101 0000 mode1 TH1=0XFD; // 76800 8倍 // 9600, 2^SMOD/32·T1 , 2^0/32*11059200 /12 /(256-0xfd)= 9600 TH1=0Xe8; // 9600, 2^SMOD/32·T1 , 2^0/32*11059200 /12 /(256-0xfd)= 9600 TL1=TH1; #else //改用STC15 新的16bit 自动装载模式 AUXR |= 0b01000000; //单时钟模式 TMOD &= 0b11001111; SCON = 0X50; // 0101 0000 mode1 8bit TH1=(65532 - (11059200 /4 /9600))>>8; // 9600, 2^SMOD/32·T1 , 2^0/32*11059200 /12 /(256-0xfd)= 9600 TL1=(65532 - (11059200 /4 /9600)); #endif PCON=0x00; //SMOD=0 , 0x80 SMOD=1 double ES=1; TR1=1; } //用T2 做波特率时钟 void uart_init_t2() { P_SW1 = P_SW1 & 0b00111111; // uart用P3口 AUXR |= 0b00010101; // T2 不分频 做 串口定时器 AUXR &= 0b11110111; //T2为定时器 AUXR2 &= 0b11111011; //禁止T2OUT IE2 &= 0b11111011; //禁止T2中断 SCON = 0X50; // 0101 0000 mode1 T2H=(65532 - (11059200 /4 /9600))>>8; // 9600, 2^SMOD/32·T1 , 2^0/32*11059200 /12 /(256-0xfd)= 9600 T2L=(65532 - (11059200 /4 /9600)); PCON=0x00; //SMOD=0 , 0x80 SMOD=1 double ES=1; TR1=1; } void spi_init() { P_SW1 = P_SW1 & 0b11110011; // SPI用P1口 SPDAT =0; SPSTAT = 0b11000000; //清除标志 SPCTL = 0b11010100; //SPI使能,主模式,clk/4 } void main(void) { EA=0; // disable all int uart_init(); //uart_init_t2(); t0_init(); //eint0_init(); spi_init(); EA =1; // enable all int //AUXR2 |= 0b00000010; //AUXR2 |= 0b00000100; sendstring("1.This is a test.\r\n"); sendstring("2.This is a test.\r\n"); while (1) { SPDAT =1; //send('a'); delay(100); test_asm(); } }
仿真运行,调试界面。