51单片机第12步_使用stdio.h库函数仿真串口通讯

发布于:2024-07-03 ⋅ 阅读:(12) ⋅ 点赞:(0)

本章介绍如何使用stdio.h库函数仿真串口通讯,学会使用view下面的“serial window #1”,实现模拟串口通讯。

Keil C51中有一些关键字,需要牢记:

interrupt0:指定当前函数为外部中断0

interrupt1:指定当前函数为定时器0中断

interrupt2:指定当前函数为外部中断1;

interrupt3:指定当前函数为定时器1中断

interrupt4:指定当前函数为串口中断;

 using 0表示当前函数使用第0组寄存器;

using 1表示当前函数使用第1组寄存器;

using 2 表示当前函数使用第2组寄存器

using 3 表示当前函数使用第3组寄存器;

51单片机内有4个工作组寄存器,每个工作组的寄存器是R0--R7

R0-R7在数据存储器里的实际地址是由特殊功能寄存器PSW里的RS1、RS0位决定的。

using 0表示设置 RS1=0,RS0 =0,用第0组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。R0(00H)....R7(07H);

using 1表示设置 RS1=0,RS0 =1,用第1组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。R0(08H)....R7(0FH);

using 2表示设置 RS1=1,RS0 =0,用第2组寄存器,R0--R7的在数据存储区里的实际地址是08H-0FH。R0(10H)....R7(17H);

using 3表示设置 RS1=1,RS0 =1,用第3组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。R0(18H)....R7(1FH);

#include <REG51.h>    //包含头文件REG51.h,使能51内部寄存器;

#include <intrins.h>  //包含头文件intrins.h,要放在stdio.h的头文件之前;

//使能函数: _nop_();  相当于汇编的NOP指令;

//使能函数: bit  _testbit_( bit bit_value ); 对bit_value进行测试,若bit_value=1,返回1,否则返回0;

//使能函数: _cror_( unsigned char x, unsigned char n ); 将字节型变量x的值,向右循环移动n位,然后将其

//值返回;

//使能函数: _iror_( unsigned int x,  unsigned char n ); 将双字节型变量x的值,向右循环移动n位,然后将

//其值返回;

//使能函数: _lror_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向右循环移动n位,然后将

//其值返回;

//使能函数: _crol_( unsigned char x, unsigned char n ); 将字节型变量x的值,向左循环移动n位,然后将其

//值返回;

//使能函数: _irol_( unsigned int x,  unsigned char n ); 将双字节型变量x的值,向左循环移动n位,然后将

//其值返回;

//使能函数: _lrol_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向左循环移动n位,然后将

//其值返回;

//以上的循环左移和循环右移,同C语言的左移和右移是不同的,使用时要小心;

#include <stdio.h>  //包含头文件stdio.h

    //_getkey();从串口读入一个字符;

   //putchar();向串口发送一个字节;

   //printf();向串口发送一串字节;

#define OSC_FREQ     11059200L

#define BAUD_Time 1

#if(BAUD_Time==1)

//若波特率加倍,则使用下面参数;

#define BAUD_57600   256 - (OSC_FREQ/192L)/57600L    //255

#define BAUD_28800   256 - (OSC_FREQ/192L)/28800L    //254

#define BAUD_19200   256 - (OSC_FREQ/192L)/19200L    //253

#define BAUD_14400   256 - (OSC_FREQ/192L)/14400L    //252

#define BAUD_9600    256 - (OSC_FREQ/192L)/9600L     //250

#define BAUD_4800    256 - (OSC_FREQ/192L)/4800L  //244

#define BAUD_2400    256 - (OSC_FREQ/192L)/2400L  //232

#define BAUD_1200    256 - (OSC_FREQ/192L)/1200L  //208

#else

//若波特率不加倍,则使用下面参数;

#define BAUD_9600    256 - (OSC_FREQ/384L)/9600L

#define BAUD_4800    256 - (OSC_FREQ/384L)/4800L

#define BAUD_1200    256 - (OSC_FREQ/384L)/1200L

#endif

#define receive_buffer_size  40

unsigned char receive_buffer[receive_buffer_size];

unsigned char next_in,next_out;

//函数功能:接收和发送中断服务函数;

void isr_UART(void) interrupt 4 using 1

{ unsigned char temp;

  if(RI) //处理接收数据;

    { temp=_getkey(); //从串口接收一个字节; 

  receive_buffer[next_in++]=temp;

      if(next_in==receive_buffer_size) next_in=0;

}

}

//函数功能:初始化串口,设置波特率为9600bps@11.0592MHz,使能接收,使用8位UART,开中断允许;

void Serial_Port_Initialization()

{ PCON = 0x80;

  SCON=0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI

             //SM1:SM0=01,选择方式1,SM2=0,表示非多机通讯,8-bit UART;

     //REN=1,使能接收;

  TMOD&=0x0f;

  TMOD|= 0x20;

//定时器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00

        //GATE=0,TR置1便可以启动Timer;GATE=1,TR置1,且INT脚输入高电平,才可以启动Timer;

   //M11:M10=10,选择方式2,8位自动重装载;

  TH1=BAUD_9600;  //TH1:  reload value for 9600 baud @11.0592MHz;

  TL1=TH1;

  TR1=1;   //启动Timer1;

  //TI=1;    //发送UART的第一个字节,为下次发送做准备;

  TI=0;    //为下次发送做准备;

  RI=0;

  next_in=0;

  next_out=0;

  ES=1; //使能串口接收和发送中断;

  EA=1; //开总中断

}

//函数功能: 将接收到的数据返回给PC;

void send_data_to_pc()

{ while(next_out!=next_in)  //将接收到的数据返回给PC;

     { TI=1; //为调用printf()和putchar()内部函数做准备;

   printf("receive_buffer[%bd]=%c\n",next_out,receive_buffer[next_out]);

   TI=0; //结束调用printf()和putchar()内部函数

    next_out++;

 }

}

//函数功能: Delay 50us

void delay_50us(unsigned char _50us)

{ while(_50us--)

{ _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

    }

}

void main(void)

{ Serial_Port_Initialization();

  //初始化串口,设置波特率为9600bps@11.0592MHz,使能接收,使用8位UART,开中断允许;

  TI=1; //为调用printf()和putchar()内部函数做准备;

  printf("Start:\n");

  TI=0; //结束调用printf()和putchar()内部函数

  for(;;)

    { _getkey(); //打开view下面的serial window #1,用键盘输入一个字符;

  send_data_to_pc(); //将接收到的数据返回给PC;

  delay_50us(20);    //延时1ms;

  TI=0; //结束调用printf()和putchar()内部函数

}

}


网站公告

今日签到

点亮在社区的每一天
去签到