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

📄 have_current_motor.c

📁 小液晶1602驱动程序是一个不错的驱动程序,是经过了本人的实现可行的程序
💻 C
字号:

#include"F240REGS.H"

//@@@@@@@@@@@@@液晶顯示程蠤@@@@@@@@@@@@@@@@@@@@@@
#define NOP()  asm(" nop")

#define lcd_data_port PEDATDIR  //八位数据
#define lcd_data_ddr  PEDATDIR    //引脚方向定义
#define lcd_busy_pin  PEDATDIR 
#define lcd_busy_ddr  PEDATDIR 
#define lcd_control_port PCDATDIR 
#define lcd_control_ddr  PCDATDIR 

#define lcd_RS_DAT 0x0004  //PORTC^2  
#define lcd_RW_DAT 0x0008  //PORTC^3     
#define lcd_EN_DAT 0x0010  //PORTC^4    

#define lcd_RS_DIR 0x0400  //PORTC^2    
#define lcd_RW_DIR 0x0800  //PORTC^3  
#define lcd_EN_DIR 0x1000  //PORTC^4  

#define busy 0x8000   //LCD_DB7 

#define busy_dat  0x0080

unsigned char number[10]={'0','1','2','3','4','5','6','7','8','9'};
int a,b,c,d,e,m,n,o,p;
//<<<<<<<<<<<<<<<<<<<<<位置控制<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,  
 long increment=0, new_place_error=0, set_place=200000;   //PI 增量
 long summation=0, x_x=0;    //纍加值

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.>


//>>>>>>>>>>>>>>>>>>>>速度定义>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
unsigned int  adc_new,adc_i,adc_sum,v_top=2500; 
unsigned int  temp, temp1, temp2,temp3,i_temp=0,sum_temp=0;
//int Kp=3,Ki=5;//Kp=0.464,Ki=0.265;
int now_error=0, old_error=0, speed_i=0, old_speed_i=0; 
int   set_v, old_set_v;
long increment;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
unsigned int adv_temp,adv_i=0,adv_dsp;
unsigned long adv_sum=0;
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
unsigned int C_i=0, C=0, I_now=0;     //电机电流显示定义
         int I_er=0,  old_I_er=0, I_c=0, max_c=1020, now_pwm, old_pwm; 
         
unsigned int  old_temp=0;

unsigned char turn=1;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int n_duty=0,nkp=22,nki=18;
int i_duty=0,ikp=31,iki=28;
/*8888888888888888888888888888888888888888(AVR中的定义)88888888888
#define lcd_data_port PORTB
#define lcd_data_ddr DDRB
#define lcd_busy_pin PINB 
#define lcd_busy_ddr DDRB 
#define lcd_control_port PORTD 
#define lcd_control_ddr DDRD 

#define lcd_RS 0x01    
//PORTD^0 
#define lcd_RW 0x02    
//PORTD^1 
#define lcd_EN 0x60   
//PORTD^2 
#define busy 0x80    
//LCD_DB7-PORTB^2 

//8888888888888888888888888888888888888888888888888888888888888888888*/
/*----------------------------------函数声明------------------------------------------*/ 
void lcd_init_portCD(void); 
void lcd_init(void); 
void lcd_write_command(unsigned char command,unsigned char wait_en); 
void lcd_write_data(unsigned char char_data); 
void wait_enable(void); 
void lcd_set_xy( unsigned char x, unsigned char y ); 
void display_a_char(unsigned char x,unsigned char y,unsigned char char_data); 
void display_a_string(unsigned char x,unsigned char y,unsigned char *ptr);
void delay(unsigned int i); 
void delay_1ms(void ); 
void delay_nms(unsigned int n) ; 
void port_init(void);
void ad_init(void);
void cpu_init(void);
void timer1_init(void);
void timer2_init(void); 
void timer3_init(void);   


/*****************************************************************
光标命令 
lcd_write_command(0x0e,0);//光标开 
lcd_write_command(0x0d,0);//光标所在字符闪烁   
lcd_write_command(0x0c,0); //光标关  
**********************************************************/ 

/*------------------------------------液晶驱动函数-------------------------------------*/ 
void lcd_init_portCD(void) 
{ 
   lcd_data_port=0xffff;   //output high
   lcd_data_ddr|=0xff00;   //output 
   lcd_control_port|=0x1C1c;  
   lcd_control_ddr|=0x1C1c; 
} 

//液晶初始化 
void lcd_init(void) 
{ 
   delay_nms(15); 
   lcd_write_command(0x38,0);//显示模式设置三次(此时不管lcd空闲与否) 
   delay_nms(5); 
   lcd_write_command(0x38,1); 
   delay_nms(5); 
   lcd_write_command(0x38,1); 
   delay_nms(5); 
    
   lcd_write_command(0x38,1);//显示模式设置(从此之后均需lcd空闲) 
   lcd_write_command(0x08,1);//显示关闭 
   lcd_write_command(0x01,1);//显示清屏 
   lcd_write_command(0x06,1);//显示光标移动设置 
   lcd_write_command(0x0c,1);//显示开及光标设置 
} 

//写指令函数: E=高脉冲 RS=0 RW=0 
void lcd_write_command(unsigned char command,unsigned char wait_en)//command为指令,wait_en指定是否要检测LCD忙信号 
{ 
   if(wait_en) wait_enable();//若wait_en为1,则要检测LCD忙信号,等待其空闲 
   lcd_control_port&=~lcd_RS_DAT;//RS=0,命令 
   lcd_control_port&=~lcd_RW_DAT;//RW=0,写操作
   lcd_control_port&=~lcd_EN_DAT;//E=0,下面给LCD一个高脉冲 
  delay(2);
  lcd_data_port=command|0xff00;
   delay(2);
   lcd_control_port|=lcd_EN_DAT;//E=1 
  delay(10); 
   lcd_control_port&=~lcd_EN_DAT;//重设E=0
} 

//写数据函数: E =高脉冲 RS=1 RW=0 
void lcd_write_data(unsigned char char_data) 
{ 
   wait_enable();//等待LCD空闲 
   lcd_control_port|=lcd_RS_DAT;//RS=1 
   lcd_control_port&=~lcd_RW_DAT;//RW=0 
   lcd_control_port&=~lcd_EN_DAT;//E=0,下面给LCD一个高脉冲 
   delay(2);
    lcd_data_port=char_data|0xff00;
	  delay(2);
   lcd_control_port|=lcd_EN_DAT;//E=1 
  delay(10);
   lcd_control_port&=~lcd_EN_DAT;//重设E=0 
} 

//正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。 
//检测忙信号,等待LCD空闲函数 
void wait_enable(void) 
{ 
   lcd_busy_ddr&=~busy;//设置busy口为输入 
   lcd_control_port&=~lcd_RS_DAT;//RS=0 
   lcd_control_port|=lcd_RW_DAT;//RW=1 
   lcd_control_port&=~lcd_EN_DAT;//E=0,下面给LCD一个高脉冲 
   delay(2); 
   lcd_control_port|=lcd_EN_DAT;//E=1
   delay(10);
   while(lcd_busy_pin&busy_dat);//等待LCD_DB7为0 
   delay(2);
   lcd_control_port&=~lcd_EN_DAT;//重设E=0 
  delay(2);
   lcd_busy_ddr|=busy;//设置busy口为输出 
} 
/**LCD_set_xy:设置LCD显示的起始位置输入参数:x、y :  
                    显示字符串的位置,X:0-15,Y:0-1 
                    LCD第一行显示寄存器地址:0X80-0X8F 
                    LCD第一行显示寄存器地址:0XC0-0XCF   ***/ 
void lcd_set_xy( unsigned char x, unsigned char y ) 
{ 
    unsigned char address; 
    if (y == 0)  
       address = 0x80 + x; 
    else  
        address = 0xc0 + x; 
    lcd_write_command(address,1);//一定需要检查忙信号,所以为1 
} 
//显示一个字符函数 
void display_a_char(unsigned char x,unsigned char y,unsigned char char_data)//char_data为要显示的字符 
{ 
    lcd_set_xy(x,y); 
    lcd_write_data(char_data); 
} 

//指定一行显示连续字符串:0显示在第一行,1显示在第二行,注字符串不能长于16个字符 
//显示一行连续字符串函数 

void display_a_string(unsigned char x,unsigned char y,unsigned char *ptr) 
{ 
//ptr:指向无符号字符型变量的指针变量,指针也就是地址,指字符串数组的首指针 
    lcd_set_xy(x,y); 
   while(*ptr)//当ptr='\0'(空指针null)跳出循环 
    { 
     lcd_write_data(*ptr);//*ptr,指向该地址的内容 
     ptr++; 
    } 
} 

/*---------------------------------------延时函数-------------------------------------*/ 
void delay(unsigned int i)    //第一次6US,以后就是2US一次
{
     unsigned int j;
    for(j=1;j<i;j++)
    { asm(" nop"); }
}

void delay_nms(unsigned   int i)  //每一次1MS
{
     unsigned  int j;
     for(j=1;j<=i;j++)
    {  delay(456); }
}

void delay_1ms(void)
{
    delay_nms(1);
}


//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

/*
void INT_enable();
void INT_disable();
void cpu_init(void) ;
void port_init(void);
void   timer2_init(void);
void   timer3_init(void);
void   timer1_init(void);
void ad_init(void);*/

 main()
{
  
   cpu_init();
   port_init();
   delay_nms(5);  
   lcd_init_portCD(); 
   delay_nms(5);
   lcd_init(); 
   delay_nms(5);
   timer1_init();
   timer2_init();
   timer3_init();
   ad_init();
  /*display_a_char(0,0,'8'); 
  display_a_char(1,0,'e'); 
  display_a_char(2,0,'t'); 
  display_a_char(3,0,'y'); */

       
   for(;;)
   {/*
    delay(2); //2.5us  delay(10) 7.5us
	PADATDIR|=(1<<2);
    delay(2);            
     PADATDIR&=~(1<<2); 
	 */
	// temp = 1234;

      a=temp3/1000;
      b=temp3%1000/100;
      c=temp3%100/10;
      d=temp3%10;
      display_a_char(0,0,number[a]); 
      display_a_char(1,0,number[b]); 
      display_a_char(2,0,number[c]); 
      display_a_char(3,0,number[d]);
	 
     
      m=adv_temp/1000;
      n=adv_temp%1000/100;
      o=adv_temp%100/10;
      p=adv_temp%10;
      display_a_char(7,0,number[m]); 
      display_a_char(8,0,number[n]); 
      display_a_char(9,0,number[o]); 
      display_a_char(10,0,number[p]); 
     
 //*****************电流显示**************     
      a=C_i/1000;
      b=C_i%1000/100;
      c=C_i%100/10;
      d=C_i%10;
      display_a_char(0,1,number[a]); 
      display_a_char(1,1,number[b]); 
      display_a_char(2,1,number[c]); 
      display_a_char(3,1,number[d]);   
        
        
        
      a=I_c/1000;
      b=I_c%1000/100;
      c=I_c%100/10;
      d=I_c%10;
      display_a_char(6,1,number[a]); 
      display_a_char(7,1,number[b]); 
      display_a_char(8,1,number[c]); 
      display_a_char(9,1,number[d]); 
	  delay_nms(500) ; 
	  }
         
   
}
//==============I/o初始化=========
//E port as LCD data
//C2 as RS, c3 as R/W, c4 as E
//eva as pwm output
void port_init(void)
{
     MCRA=0xfffb;  //enable qep and pwm1~6 写一使能特殊功能,写0使能I/O功能
     //MCRB=0X0000;      
     MCRC=0x0000;
	PCDATDIR=0x1c00;  /*高八位是方向,C2~C4口输出,低八位是数据*/
     PEDATDIR=0xff00;  /*高八位是方向,E口输出,低八位是数据*/
   //  PBDATDIR=0X0000;
    // PCDATDIR=0X0000;
    // PDDATDIR=0X0000;
     PADATDIR|=0X0404;  //A2 as output,high
    // PEDATDIR&=~(1<<2);
     PFDATDIR=0X0000;
        
}

//=============AD轉換=============
void ad_init(void)
{
    EVAIFRA=0XFFFF;  //标志位清零
    GPTCONA=0X0100;  //触发AD---週期中斷標誌
	MAXCONV=0X01;    //选择2个通道
	CHSELSEQ1=0X030;//选用通道3&&0
	ADCTRL1=0X0900;   //ADC控制寄存器1,采样时间设置,双排序,启/停模式
	ADCTRL2=0X0500;  //用SEQ1,中EVA启动
}
/*********************************/


//=========中断开关=======
void INT_enable()
{
     asm(" clrc INTM");   //中断允许
}

void INT_disable()
{
     asm(" setc INTM");  //中断禁止
}
/******************************/
//===========CPU初始化===========
void cpu_init(void)    
{
    asm(" setc SXM");  //符号位扩展有效
    asm(" clrc OVM");  //累加器中结果正常溢出
    asm(" clrc CNF");  //B0被配置成数据存储空间
    INT_enable();     //开中断
    SCSR1=0X02FE;   //2倍频,15MHz*2=30MHz
    WDCR=0X00E8;   //禁止看门狗
    IMR=0x0003;    //中断设置
    IFR=0XFFFF;    //清除中断标志位:写1清除
    WSGR &= 0xf800;     //禁止所有等待状态
    
      
}

//==========定时器1初始化程序===============PWM
void timer1_init(void)
{
     //EVAIMRA=EVAIMRA|0x0080; //允许timer1的周期中断
     //EVAIFRA=EVAIFRA&0X0080; //清除定时器1周期中断标志
     T1CON=0X1046;           //timer1为连续增计数,不分频,内部时钟,
     COMCONA=0Xa600;        //周期重装
	 CAPCONA = 0xe000;       // 使能QEP
     ACTRA=0X0001;           //PWM1高有效
     T1PR=1024;           //比较上限值,时钟频率30MHz,开关频率29KHz
     CMPR1=10;           //比较初值
     //CMPR2=500;
    // CMPR3=900;
     T1CNT=0;           //TIMER1计数器清零
}
/*************************************/

//=============TIMER2_INIT=============QEP
void timer2_init(void)
{
     T2PR=0xffff;       //定时器最大值
     T2CON=0X1870;    //定向增/減计数,使能QEP
     T2CNT=0;         //计数器出始值为0
   
  //   EVAIMRB|=0X0001; //允许中断
}

/*************************************/

/*************************************/
void timer3_init()
{
    // T3PR=937;       //定时1MS
     T3PR=1875;       //定时2MS
     T3CON=0X1540;    //增计数

⌨️ 快捷键说明

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