文件夹 e:\dpj\20210101
目标 STC15W4K32S4
proteus 新建单片机 串口 分压调节电压源 更改单片机主频为11059200
虚拟串口软件安装及配置
单片机使用COM4 串口调试器使用COM3 波特率 115200
ADC读取电压数据正常 P1.0 P1.1
串口通讯测试正常 ADC 通过可变电阻调节电压后 模拟量变化发送串口
串口通讯测试正常 中断接收<>之间字符,回送 因地址空间,字符个数<10
程序运行时间以protues左下角的运行时间为准 见截图
定时器设置及中断处理 以1ms为周期,每3000ms在串口发送字符
串口命令设置定时器发送数据到串口的时间间隔 <后的第一个字符为A 第二个为数字 表示间隔秒数
仿真原理图如下(STC15W4K32S4单片机proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- /*---------------------------------------------------------------------*/
- /* --- STC MCU Limited ------------------------------------------------*/
- /* --- STC15F4K60S4 系列 定时器1用作串口1的波特率发生器举例------------*/
- /* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
- /* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序 */
- /*---------------------------------------------------------------------*/
- //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
- //若无特别说明,工作频率一般为11.0592MHz
- #include "STC15Fxxxx.H"
- //#include "reg51.h"
- #include <stdio.h>
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- //typedef unsigned int u16; //对数据类型进行声明定义
- //typedef unsigned char u8;
- #define FOSC 11059200L //系统频率
- #define BAUD 115200 //串口波特率
- #define NONE_PARITY 0 //无校验
- #define ODD_PARITY 1 //奇校验
- #define EVEN_PARITY 2 //偶校验
- #define MARK_PARITY 3 //标记校验
- #define SPACE_PARITY 4 //空白校验
- #define PARITYBIT NONE_PARITY //定义校验位
- /* STC15Fxxxx.H中已定义
- //sfr P0M1 = 0x93;
- //sfr P0M0 = 0x94;
- //sfr P1M1 = 0x91;
- //sfr P1M0 = 0x92;
- //sfr P2M1 = 0x95;
- //sfr P2M0 = 0x96;
- //sfr P3M1 = 0xb1;
- //sfr P3M0 = 0xb2;
- //sfr P4M1 = 0xb3;
- //sfr P4M0 = 0xb4;
- //sfr P5M1 = 0xC9;
- //sfr P5M0 = 0xCA;
- //sfr P6M1 = 0xCB;
- //sfr P6M0 = 0xCC;
- //sfr P7M1 = 0xE1;
- //sfr P7M0 = 0xE2;
- //sfr AUXR = 0x8e; //辅助寄存器
- //sfr P_SW1 = 0xA2; //外设功能切换寄存器1
- */
- #define S1_S0 0x40 //P_SW1.6
- #define S1_S1 0x80 //P_SW1.7
- #define ADC_POWER 0x80 //ADC电源控制位
- #define ADC_FLAG 0x10 //ADC完成标志
- #define ADC_START 0x08 //ADC起始控制位
- #define ADC_SPEEDLL 0x00 //540个时钟
- #define ADC_SPEEDL 0x20 //360个时钟
- #define ADC_SPEEDH 0x40 //180个时钟
- #define ADC_SPEEDHH 0x60 //90个时钟
- //sbit P22 = P2^2;
- unsigned int ch;a,b;
- unsigned int dd=0;
- unsigned int cc=0;
- unsigned int cc0=0;
- unsigned int cc1=0;
- unsigned int cc00=0;
- unsigned int cc01=0;
- unsigned int cc10=0;
- unsigned int cc11=0;
- unsigned int time0count0 = 0 ;
- unsigned int time0count1 = 0 ;
- unsigned int time0count = 3000 ;
- bit busy;
- char receivechar = 0;
- int receive_count = 0;
- int received = 0;
- WORD receivestr[10];
- void InitUart();
- void InitADC();
- void Timer0Init();
- void SendData(BYTE dat);
- void SendString(char *s);
- void serial_put_uint(unsigned int number);
- void Delay(WORD n);
- //void ShowResult(BYTE ch);
- unsigned int GetADCResultint(BYTE ch);
- void main()
- {
- int initreceivestrcount=0;
- unsigned int tt0=0,tt1=0;
- // unsigned int d1,d2,d3,i;
- unsigned int i=0;
- if (i == 0 ) //初始化tt0 tt1 P0 -P7 数据
- {
- /*
- 例如将P1M0=0X60和P1M1=0X00译成bai二进制代码是
- P1M0=0110 0000,duP1M1=0000 0000.
- 按照I/O口工作模式设置zhi规定
- 都为0时为准双向口(dao传统8051单片机zhuanI/O口模式)
- 为0,1时为推挽(shu强上拉输出),
- 为1,0时为高阻(仅输入),
- 为1,1时为开漏(内部上拉断开,须外加上拉电阻)
- 你选择的是P1M0和P1M1所以针对的是P1口的操作,
- 将两个二进制代码一位位的比较可知:P1.0~P1.4及P1.7都为0,
- 故这些I/O口设置的是标准状态;P1.5和P1.6为高阻态
- (P1M0上的第六位和第七位都为1,P1M1上的第六位和第七位都是0。1,0时为高阻)
- */
- tt0=16640;
- tt1=tt0/256;
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x03;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P6M0 = 0x00;
- P6M1 = 0x00;
- P7M0 = 0x00;
- P7M1 = 0x00;
- }
- InitUart(); //初始化串口
- //printf ("20200102 第一次调试 a 1 取左字节 a %d A/256=A %d C51\n" , tt0,tt1 ); /* ?? "Hello C51 " */
- SendString("20200102 第二次调试 \r\n");
- initreceivestrcount=0;
- while (initreceivestrcount<10) //初始化 receivestr
- {
- receivestr[initreceivestrcount]=0;
- initreceivestrcount = initreceivestrcount + 1 ;
- }
- //printf ("Hello"); //printf 不能使用 编译通过 不能仿真运行
- InitADC(); //初始化ADC
- Timer0Init(); //定时器0初始化
- /* 除法测试
- //printf ("Hello ADC 第y次调试 a 1 加代码a %d A/256=A %d C51\n" , tt0,tt1 );
- // sprintf(str," receive %d \r\n",receivechar);
- // SendString(str);
- // sprintf(str," d1 %d a \r\n",tt0);
- // SendString(str);
- // sprintf(str," d2 %d a \r\n",tt1);
- // SendString(str);
- // sprintf(str," d3 %d a \r\n",d3);
- // SendString(str);
- */
- SendString("c STC15W4kS32\r\n Uart Test !\r\n");
- while(1)
- {
- if (received == 1) // 在串口接收预定义字符后回送 20210103 增加控制定时显示功能
- {
- /* 除法测试及sprintf
- // SendString("\r\n");
- // d1 = receivechar;
- // d2 = d1 ;
- // d3=d2*256;
- // d3=d1-d3;
- // sprintf(str," receive %d a\r\n",receivechar);
- // SendString(str);
- // sprintf(str," d1 %d b \r\n",d1);
- // SendString(str);
- // sprintf(str," d2 %d c \r\n",d2);
- // SendString(str);
- // sprintf(str," d3 %d d \r\n",d3);
- // SendString(str);
- // SendString(receivestr);receivechar
- */
- serial_put_uint(receivechar);
- SendString(" start ");
- //serial_put_uint(11);
- for (i=0;i<receive_count;i++)
- {
- SendData(receivestr[i]);
- }
- SendString(" COUNT= ");
- serial_put_uint(receive_count);
- receive_count = 0 ;
- if (receivestr[1] == 65 )
- {
- time0count = ( receivestr[2] - 48 ) * 1000 ;
- SendString(" \r\n 串口设定 time0 ");
- serial_put_uint(time0count/1000);
- SendString(" 秒定时 ");
- }
- SendString(" \r\n");
- received = 0 ;
- }
- if (time0count0 != time0count1) // 串口设定的秒定时
- {
- SendString(" time0 ");
- serial_put_uint(time0count/1000);
- SendString(" 秒定时 执行 ");
- serial_put_uint(time0count0);
- SendString(" \r\n ");
- time0count1 = time0count0;
- }
- b=b+1;
- dd=0;
- cc00 = GetADCResultint(dd); //读取ADC 0 P1.0 数据
- if (cc01 != cc00) // ADC 0 P1.0 数据变化发送串口
- {
- SendString(" ADC ");
- // serial_put_uint(b);
- SendString(" ch ");
- serial_put_uint(dd);
- SendString(" new ");
- serial_put_uint(cc00);
- SendString(" old ");
- serial_put_uint(cc01);
- SendString(" end \r\n");
- //printf (" ADC %d ch %d :0x %x 0d %d \n", b,dd,cc00,cc01 );
- cc01 = cc00;
- }
- dd=1;
- cc10 = GetADCResultint(dd); //读取ADC 1 P1.1 数据
- if (cc11 != cc10) // ADC 1 P1.1 数据变化发送串口
- {
- SendString(" ADC ");
- // serial_put_uint(b);
- SendString(" ch ");
- serial_put_uint(dd);
- SendString(" new ");
- serial_put_uint(cc10);
- SendString(" old ");
- serial_put_uint(cc11);
- SendString(" end \r\n");
- //printf (" ADC %d ch %d :0x %x 0d00 %d \n", b,dd,cc10,cc11 );
- cc11=cc10;
- }
- dd=0;
- if (b>10000) b=0;
- }
- }
- /*******************************************************************************
- * 函 数 名 : Timer0Init
- * 函数功能 : 定时器0初始化
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Timer0Init()
- {
- TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
- TH0=0XFC; //给定时器赋初值,定时1ms
- TL0=0X18;
- ET0=1;//打开定时器0中断允许
- EA=1;//打开总中断
- TR0=1;//打开定时器
- }
- /*----------------------------
- 初始化串口
- ----------------------------*/
- void InitUart()
- {
- // ACC = P_SW1;
- // ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
- // P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
-
- // ACC = P_SW1;
- // ACC &= ~(S1_S0 | S1_S1); //S1_S0=1 S1_S1=0
- // ACC |= S1_S0; //(P3.6/RxD_2, P3.7/TxD_2)
- // P_SW1 = ACC;
- //
- // ACC = P_SW1;
- // ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=1
- // ACC |= S1_S1; //(P1.6/RxD_3, P1.7/TxD_3)
- // P_SW1 = ACC;
- #if (PARITYBIT == NONE_PARITY)
- SCON = 0x50; //8位可变波特率
- #elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
- SCON = 0xda; //9位可变波特率,校验位初始为1
- #elif (PARITYBIT == SPACE_PARITY)
- SCON = 0xd2; //9位可变波特率,校验位初始为0
- #endif
- AUXR = 0x40; //定时器1为1T模式
- TMOD = 0x00; //定时器1为模式0(16位自动重载)
- TL1 = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
- TH1 = (65536 - (FOSC/4/BAUD))>>8;
- TR1 = 1; //定时器1开始启动
- ES = 1; //使能串口中断
- EA = 1;
-
-
-
- // SCON = 0x5a; //设置串口为8位可变波特率
- //#if URMD == 0
- // T2L = (65536 - (FOSC/4/BAUD));
- // T2H = (65536 - (FOSC/4/BAUD)) >> 8;
- // AUXR = 0x14; //T2为1T模式, 并启动定时器2
- // AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
- //#elif URMD == 1
- // AUXR = 0x40; //定时器1为1T模式
- // TMOD = 0x00; //定时器1为模式0(16位自动重载)
- // TL1 = (65536 - (FOSC/4/BAUD));
- // TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
- // TR1 = 1; //定时器1开始启动
- //#else
- // TMOD = 0x20; //设置定时器1为8位自动重装载模式
- // AUXR = 0x40; //定时器1为1T模式
- // TH1 = TL1 = (256 - (FOSC/32/BAUD));
- // TR1 = 1;
- //#endif
- }
- /*----------------------------
- 初始化ADC
- ----------------------------*/
- void InitADC()
- {
- P1M0 =1;
- P1M1 =0;
- P1 = 0Xff;
- P1ASF = 0xff; //设置P1口为AD口
- ADC_RES = 0; //清除结果寄存器
- ADC_RESL = 0; //清除结果寄存器
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- Delay(2); //ADC上电并延时
- }
- /*----------------------------
- 读取ADC结果 20210101 注释GetADCResult 用GetADCResultint代替
- ----------------------------*/
- unsigned int GetADCResultint(BYTE ch)
- {
- unsigned int ret=0;
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- _nop_(); //等待4个NOP
- _nop_();
- _nop_();
- _nop_();
- while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
- ADC_CONTR &= ~ADC_FLAG; //Close ADC
- ret = ADC_RES*4 + ADC_RESL;
- return ret; //返回ADC结果
- }
- /*----------------------------
- UART 中断服务程序
- -----------------------------*/
- void Uart() interrupt 4
- {
- if (RI)
- {
- RI = 0; //清除RI位
- receivechar = SBUF; //P0显示串口数据
- if ( receivechar == 60 ) receive_count = 0 ;
- if ((receive_count<9) && ( receivechar != 62 )&&(received == 0 ))
- {
- receivestr[receive_count] = receivechar;
- receivestr[receive_count+1] = 0;
- receive_count = receive_count + 1 ;
-
- }
- else
- {
- received = 1;
- // while (initreceivestrcount<10)
- // {
- // receivestr[initreceivestrcount]=0;
- // initreceivestrcount = initreceivestrcount + 1 ;
- // }
-
- }
- // SendData(receivechar);
- // P22 = RB8; //P2.2显示校验位
- }
-
- if (TI)
- {
- TI = 0; //清除TI位
- busy = 0; //清忙标志
- }
- }
- void Timer0() interrupt 1
- {
- static u16 itime0;
- TH0=0XFC; //给定时器赋初值,定时1ms
- TL0=0X18;
- itime0++;
- if(itime0==time0count)
- {
- itime0=0;
- time0count0 = time0count0 + 1;
- if ( time0count0 > 20 ) time0count0 = 0;
- }
- }
- /*----------------------------
- 发送串口数据
- ----------------------------*/
- void SendData(BYTE dat)
- {
- while (busy); //等待前面的数据发送完成
- ACC = dat; //获取校验位P (PSW.0)
- // if (P) //根据P来设置校验位
- // {
- //#if (PARITYBIT == ODD_PARITY)
- // TB8 = 0; //设置校验位为0
- //#elif (PARITYBIT == EVEN_PARITY)
- // TB8 = 1; //设置校验位为1
- //#endif
- // }
- // else
- // {
- //#if (PARITYBIT == ODD_PARITY)
- // TB8 = 1; //设置校验位为1
- //#elif (PARITYBIT == EVEN_PARITY)
- // TB8 = 0; //设置校验位为0
- //#endif
- // }
- busy = 1;
- SBUF = ACC; //写数据到UART数据寄存器
- }
- /*----------------------------
- 发送字符串
- ----------------------------*/
- void SendString(char *s)
- {
- // EA = 0 ;
- // ES = 0 ;
- while (*s) //检测字符串结束标志
- {
- SendData(*s++); //发送当前字符
- }
- // EA = 1 ;
- // ES = 1 ;
- }
- void serial_put_uint(unsigned int number)
- {
- unsigned int i;
- unsigned int nTmp;
- // *s++ =num/10 +'0';
- //*s++=num%10 +'0';
- //*s =0;
-
- //感觉这写法怪怪的吗?干嘛不for(i=1;i<5;i++) 因为这样不需要使用库函数pow()
- for(i=10000;i>=1;i=i/10)
- {
- nTmp = number/i;
- if(nTmp >=1 ) SendData((unsigned char)(nTmp%10 + 0x30));
- }
- }
- /*----------------------------
- 软件延时
- ----------------------------*/
- void Delay(WORD n)
- {
- WORD x;
- while (n--)
- {
- x = 5000;
- while (x--);
- }
- }
复制代码
所有资料51hei提供下载:
20210103a.rar
(580.92 KB, 下载次数: 243)
|