📄 have_current_motor.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 + -