⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text1.c

📁 c8051f系列单片机电机控制C语言源代码
💻 C
字号:
#include "c8051F040.h"
#define uchar unsigned char
#define uint unsigned int

#define Motor_start     0x10     // 电机开启命令
#define Motor_stop      0x20     // 电机停止命令
#define Motor_control   0x30     // 接收数据的包头信号
#define Motor_turn      0x01     // 电机正转
#define Motor_Anti_turn 0x02     // 电机反转

bit Motor_Flag_turn=0;           // 电机转动与停止转动的标志位

sbit Motor_CP        =P4^1;
sbit Motor_DIR       =P4^0;

sbit LED=P1^6;  // 对LED操作的时候要先 SFRPAGE = CONFIG_PAGE;  

xdata uchar uart0_data[5]={0xfe,0xcc,0x02,0x00,0x00};
uint pulse_num=0x0000;  // 从串口接收到的脉冲数,脉冲数16进制高8位和低8位合并一个16位
uint Time0_num_LED=0;     // 定时器中断次数,定时器每定时累积到1秒LED取反一次

// uart0_data[0]= TH0
// uart0_data[1]= TL0
// uart0_data[2]= 0x01正转 / 0x00反转
// uart0_data[3]= 脉冲数16进制高8位
// uart0_data[4]= 脉冲数16进制低8位

void port_init(); // 端口初始化函数
void os_init();   // 系统时钟初始化,选择外部晶体振荡器
void uart_init(); // 串口初始化,选择UART0
void time01_init(); // 定时器1初始化,作为UART0的波特率发生器,定时器0初始化


void delay(int tim)
{ 
  int i,j;
  for(i=0;i<tim;i++)
    {
      for(j=0;j<i;j++);
	}
}

/*************************************************************************
*主函数
**************************************************************************/
void main()
{
	WDTCN = 0xDE;                                   // 关闭看门狗
	WDTCN = 0xAD;

	os_init();                                      // 晶振初始化
	port_init();									// 端口初始化
	uart_init();                                    // 串口初始化,选择UART0
	time01_init();                                  // 定时器初始化,作为UART0的波特率发生器
	SFRPAGE   = CONFIG_PAGE;  

	IE  = 0x92;		// 开中断 bit7=EA 全局总中断
  
	while(1)
	{
      if(Motor_Flag_turn==1) 
	    {
		  SFRPAGE   = TIMER01_PAGE;
		  TR0=1; 
		}
      if(Motor_Flag_turn==0) 
	    {
		  SFRPAGE   = TIMER01_PAGE;
		  TR0=0;

		  SFRPAGE   = CONFIG_PAGE;  
		  LED=1;
		}
      if(pulse_num==0)	
	    {
          SFRPAGE = UART0_PAGE;
	      SBUF0=0x20;
		  Motor_Flag_turn=0;
 	    }
      if(pulse_num!=0)	
	    {
		  Motor_Flag_turn=1;
		  SFRPAGE = UART0_PAGE;
		  SBUF0=uart0_data[2];
 	    }
	  delay(1000);
	}

}

// uart0_data[0]= TH0
// uart0_data[1]= TL0
// uart0_data[2]= 0x01正转 / 0x00反转
// uart0_data[3]= 脉冲数16进制高8位
// uart0_data[4]= 脉冲数16进制低8位
void time0 (void) interrupt 1
{
   char i;

//   TR0=0; // 先停止计数,来赋值   
   TH0=uart0_data[0];
   TL0=uart0_data[1];  // 赋脉冲频率值
//   TR0=1;

   if(Time0_num_LED==0x07d0)  // 2000*0.0005=1秒
     {
	  SFRPAGE   = CONFIG_PAGE;  
	  Time0_num_LED=0;
	  LED=~LED;
	 }
   else  Time0_num_LED++;

   SFRPAGE   = TIMER01_PAGE;



if(pulse_num !=0)
 {
  i=uart0_data[2];
  SFRPAGE   = CONFIG_PAGE;
  if(i==Motor_turn)  // 电机正转
    {
	   SFRPAGE   = CONFIG_PAGE;
       pulse_num--;       
       Motor_DIR=1;	
       Motor_CP=~Motor_CP ;
    }
  if(i==Motor_Anti_turn) // 电机反转
    {
	   SFRPAGE   = CONFIG_PAGE;
       pulse_num--;
       Motor_DIR=0;
       Motor_CP=~Motor_CP ;
    }
 }
}


void UART0 (void) interrupt 4
{
    uchar i,j;
	uint temp=0x0000;
    SFRPAGE = UART0_PAGE;
   if(TI0==1) TI0=0;	
   if(RI0==1)
	{	              	
	    ET0=0; // 关定时器0中断  要置串口中断的优先级高于定时器中断	        
        RI0=0;
		i=SBUF0;
		if(i==Motor_start) Motor_Flag_turn=1;
        if(i==Motor_stop)  Motor_Flag_turn=0;
		if(i==Motor_control)
		  {
		    ES0=0;
            SFRPAGE = UART0_PAGE;
		    for(j=0;j<5;j++)
			 {			    
			    while(RI0==0);
		        RI0=0;
                uart0_data[j]=SBUF0;
			 }

             ES0=1;
	        
			 pulse_num=0x0000;      // 从串口接收到的脉冲数,脉冲数16进制高8位和低8位合并一个16位
	         temp=uart0_data[3];  // 脉冲数16进制高8位
			 temp=temp<<8;;
	         pulse_num=temp;
			 temp=0x0000;
			 temp=uart0_data[4];  // 脉冲数16进制低8位
	         pulse_num=pulse_num|temp;  
		  }
		 ET0=1; // 开定时器0中断
    }
}

/*************************************************************************
*
*端口初始化函数
**************************************************************************/
void port_init()
{
    SFRPAGE   = CONFIG_PAGE;
// XBR0,XBR1,XBR2,XBR3为I/O端口寄存器
    XBR0      = 0x04;  //bit2=1,UART0 TX0配置到P0.0,RX0配置到P0.1
    XBR2      = 0x40;  
//bit6=1,Crossbar开启,用法:交叉开关配置时,为了防止配置过程中功能引脚
//产生干扰,在引脚配置过程中,将XBARE清0,配置结束后,再将其置1,使交叉开关生效

   	P0MDOUT=0X10;//P0口输出模式控制, 1:相应口为推挽输出模式
	P1MDOUT=0xff;
	P1MDIN=0xff;
	P4MDOUT=0xff;

  
}
/*************************************************************************
*系统时钟初始化,选择外部晶体振荡器  外部22.1184M晶振
**************************************************************************/
void os_init()
{
    int i = 0;
    SFRPAGE   = CONFIG_PAGE;
    OSCXCN    = 0x67;									//外部22.1184M晶振
// 0110 0111,bit6-4:110为外部石英晶振模式,bit2-0:111为设置外部晶振驱动电流配置表,书150页

    for (i = 0; i < 3000; i++);                         //等待外部晶振稳定 
    while ((OSCXCN & 0x80) == 0); //OSCXCN的bit7位为只读,外部晶振稳定运行时为1
    CLKSEL    = 0x01; //bit7-1保留,bit0为1时SYSCLK采用外部时钟

}
/*************************************************************************
*串口初始化,选择UART0
**************************************************************************/
void uart_init()
{
    SFRPAGE   = UART0_PAGE;
    SCON0     = 0x50;						//允许uart0接收
// 0101 0000,bit4=1为UART0接收开启,bit7-6:01为模式1,8位UART可变波特率异部传输
}

/*************************************************************************
*定时器初始化,作为UART0的波特率发生器
*************************************************************************/
void time01_init()
{
    SFRPAGE   = TIMER01_PAGE;
    TMOD=TMOD&0x0F;   
    TMOD=TMOD|0x20;     //bit5-4=T1M1-T1M0=10为T1模式为2,8位自动重载定时/计数器
    CKCON=CKCON&0XEF; //先将bit4清0,然后再赋值
    CKCON=CKCON|0X10; //bit4=1,T1时钟为系统时钟
    TH1=0xb8;   //0xb8=184: 22.1184 M /(256-184) * 1/32=9600
    ET1=0;              // 不允许T0中断

//  TR1=1; 这里不能用这句,因为开了TR1,下面的定时器0的初始化对TMOD等操作无效了
//  所以要等定时器1和定时器0都初始化完了,再开TR1和TR0置为1

    SFRPAGE   = TIMER01_PAGE;
    TMOD=TMOD&0xF0;
    TMOD=TMOD|0x01;  // 模式1(16位定时/计数器),仅受TR0控制
    CKCON=CKCON&0xF7;  // 先将bit3清0,然后再赋值
    CKCON=CKCON|0x00;  // bit3=0,T0时钟为系统时钟由SCA1~SCA0决定

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -