zzaaa 发表于 2010-4-7 20:44:18

我公司产品成熟使用的AVR电机控制算法

//***************************FileName:Motor.C************************
//***************************ICCAVR6.30编译**************************
#include <io8535v.h>
#include <macros.h>
#include <eeprom.h>

//***************************全局变量定义**************************//
#define U1 5
char Data;               //接收数据数组
int adress;                  //数据地址
int a;                     //采样时间次数
float t;                     //采样时间.s
int itime;                   //给定采样时间的次数
int Ek=0;                  //本次偏差
int Ek_1=0;                  //上次偏差
int Ek_2=0;                  //上上次偏差
char flage=0;                //监控标志
union chang1               //float数据与char数据转换
{char c;   
float x;
}floatxin;
union chang2               //int数据与char数据转换         
{char c;
int x;
}intxin;

//**************************串口数据发送函数***********************//
//说明:串口数据发送采用查询方式,每一帧发送10个字节
void Putdata(char data)
{int i;
for(i=0;i<=9;i++)
{while(!(USR&(1<<UDRE)));
UDR=data;}
}

//**************************读AD转换结果***************************//
int GetOutputADC()
{int temp;
temp=ADCH;
temp=temp<<8;
return(temp+ADCL);
}

//***************************电机加速函数**************************//
void Upspeed()
{EEPROMReadBytes(0x0010,intxin.c,2);
intxin.c+=Data;
intxin.c+=Data;
EEPROMWriteBytes(0x0010,intxin.c,2);
}

//***************************电机减速函数**************************//
void Downspeed()
{
EEPROMReadBytes(0x0010,intxin.c,2);
intxin.c-=Data;
intxin.c-=Data;
EEPROMWriteBytes(0x0010,intxin.c,2);
}

//***************************PID调节函数***************************//
void PIDB()
{int y;         //本次速度值
float u;         //电压差值
int z;         //输出增量
int t;         //采样时间
char temp1;      //暂存
int i;
int speed;       //速度设定
float k;      //PID参数记录
for (i=0;i<=2;i++)
{EEPROMReadBytes(i*4,floatxin.c,4);
   k=floatxin.x;}
EEPROMReadBytes(0x0010,intxin.c,1);   //读EEPROM
speed=intxin.x;
t=itime*0.0001275;
y = TCNT1;
Ek=y-speed;
u=k*((Ek-Ek_1)+(t/k)*Ek+(k/t)*(Ek-2*Ek_1+Ek_2));
z=u/U1*0xFF;
temp1=OCR2;
if(flage==1)                            //监控状态
{Data=0xD0;
   Data=temp1;
   Data=y>>8;
   Data=y;
   Putdata(Data);}
temp1=temp1+z;
if(temp1<=0)                           //结果小于0时输出0
   temp1 = 0x00;
if(temp1>=0xF0)                        //结果大于0xF0时输出0xF0
   temp1 = 0xF0;
OCR2=temp1;
Ek_2 = Ek_1;
Ek_1 = Ek;
TCNT1 = 0x0000;                        //计数器清零
}

//***************************串口初始化函数************************//                  
void USARTInit(int baudrate)   
{UCR = (1<<TXEN)|(1<<RXCIE)|(1<<RXEN);    //设置收发使能,接受中断允许
UBRR = baudrate;                        //设置波特率寄存器
}

//***************************读EEPROM函数**************************//
void Eepromdata(void)
{if((adress==0x0000)||(adress==0x0004)||(adress==0x0008)) //地址判断
EEPROMReadBytes(adress,&Data,4);
else
EEPROMReadBytes(adress,&Data,2);
switch(adress)
{case 0x0000:Data=0xE4;break;
case 0x0004:Data=0xE5;break;
case 0x0008:Data=0xE6;break;
case 0x000C:Data=0xE7;break;
case 0x000E:Data=0xE8;break;
case 0x0010:Data=0xE9;break;
default :break;}
}

//***************************读数据函数****************************//
void readdata(char data)
{int trandata;
char tempdata;
if(data==0xE)
Eepromdata();
else
{switch(data)
{case 1:trandata=TCNT1;break; //读TCNT1
   case 2:trandata=(int)(tempdata=TCNT0);break;//读TCNT0
   case 3:trandata=GetOutputADC();break;//读A/D转换结果
   default :break;}
Data=(char)trandata;//数据低八位
Data=(char)(trandata>>8);//数据高八位
}
Putdata(Data);
}

//***************************命令函数******************************//
void order(void)
{switch (Data)
{case 0xC0:PORTB=PORTB|0x04;break;    //停止
case 0xC1:PORTB=PORTB&0xFB;break;    //启动
case 0xC2:                           //正转
         {PORTB=PORTB&0xFC|0x02;
                  PORTD=PORTD&0x3F|0x40;
                        break;}
case 0xC3:                           //反转
         {PORTB=PORTB&0xFC|0x01;
                  PORTD=PORTD&0x3F|0x80;
                        break;}
case 0xC4:Upspeed();break;         //加速
case 0xC5:Downspeed();break;         //减速
case 0xC6:                           //制动
         {PORTB=PORTB|0x03;
                  PORTD=PORTD&0x3F;
                        break;}
case 0xC8:flage=1;break;             //监控
case 0xC9:flage=0;break;             //退出监控
default :break;
}
}


//***************************数据处理函数**************************//
void Datadisposal(void)
{char operation;
int temp;
operation=Data;
temp=Data;
temp=temp<<8;
adress=temp+Data;
switch(operation&0x0F)
{case 0:readdata(operation>>4);break;
case 1:EEPROMWriteBytes(adress,&Data,2);break;
case 2:order();break;
default :break;
}
}

//***************************主函数********************************//
void main()
{USARTInit(25);            //初始化串口            
TCNT1=00;                   //定时器1初始化
TCCR1B=0x06;
DDRB=0x0F;                  //I/O口初始化
DDRD=0xC0;   
TIMSK=0x40;               //中断初始化
OCR2 = 0x0F;                //PWM初始化
TCCR2=0x72;
PORTB=PORTB&0xFC|0x01;
PORTD=PORTD&0x3F|0x80;
SEI();
do{} while(1);            //等待中断
}

//***************************串行接收中断服务程序******************//
#pragma interrupt_handler UART_RXC:12
void UART_RXC(void)
{char i=0;
CLI();
Data=UDR;
if(Data==0x55)         //起始位检测
{do
{while(!(USR&(1<<RXC)));
   i++;
   Data=UDR;
   if(i==9)
   break;} while(1);
if((Data==0xFE)&&(Data==0xFF))//检测结束位
Datadisposal();}
SEI();
}

//***************************定时器2中断服务程序*******************//
#pragma interrupt_handler TIM2_OVF:5
void TIM2_OVF(void)   
{CLI();
EEPROMReadBytes(0x000C,&itime,2);//读采样次数
a++;
if(a==itime)                //时间窗口判断,
{a = 0;
   PIDB();}
SEI();
}
点击此处下载 ourdev_544343.rar(文件大小:48K) (原文件名:我公司产品成熟使用的AVR电机控制算法.rar)

eripro 发表于 2010-4-7 20:48:02

mark,说不定什么时候用到

zuoyi 发表于 2010-4-7 20:50:48

留下了

ywl0409 发表于 2010-4-7 21:20:57

成熟吗?

smartzou 发表于 2010-4-7 21:23:40

爪印..

2004353215 发表于 2010-4-7 21:26:31

./emotion/em025.gif

zzh241 发表于 2010-4-7 21:41:36

mark

zzaaa 发表于 2010-4-7 22:05:35

使用iccavr编译。参考价值很高。

EISA 发表于 2010-4-7 22:14:36

mark

mcu_lover 发表于 2010-4-7 22:16:18

谢谢

avrpicarm 发表于 2010-4-7 22:19:48

不错

NeverStop 发表于 2010-4-7 22:28:07

没找到使用说明, 介绍一下硬件环境好吗?

zhc7302 发表于 2010-4-7 22:31:33

mark

j805 发表于 2010-4-7 22:35:35

mark

cjr82123 发表于 2010-4-7 22:44:54

记下

lwy86 发表于 2010-4-7 22:47:57

mark

wenwu 发表于 2010-4-7 22:50:53

配点说明就更好了。

ylei12 发表于 2010-4-7 23:01:00

有用

sky_walker 发表于 2010-4-7 23:15:07

配点说明就更好了

randyzzy 发表于 2010-4-7 23:20:08

来点接口说明就好了!

zj_t 发表于 2010-4-7 23:22:06

mark

mysky 发表于 2010-4-8 08:40:52

mark

xinbadaz 发表于 2010-4-8 09:12:56

mark,谢谢。

gxy508 发表于 2010-4-8 09:16:23

mark

cyberjok 发表于 2010-4-8 09:18:45

回复【3楼】ywl0409 老黄牛
成熟吗?
-----------------------------------------------------------------------

熟了,可以吃了...

sun424 发表于 2010-4-8 09:19:57

记号

kanprin 发表于 2010-4-8 09:41:52

仅看一下串口接收部分,问题不小。
假如某个干扰引起中断,不知道要等到啥时候才能退出中断了?
既已用中断接收,在中断里面为何又去用查询接收?
.....

maple_lu 发表于 2010-4-8 09:53:28

收下看看先

Spunky 发表于 2010-4-8 10:06:00

mark

logics 发表于 2010-4-8 10:12:33

Mark。

benladn911 发表于 2010-4-8 10:18:39

有参考价值,谢了~

eric_wang 发表于 2010-4-8 10:20:02

mark

tomhe666 发表于 2010-4-8 10:25:27

收藏

gdmfq 发表于 2010-4-8 11:27:36

收藏

bsz84 发表于 2010-4-8 11:34:51

mark

liumaojun_cn 发表于 2010-4-8 12:44:36

mark

woodtower 发表于 2010-4-8 12:57:18

mark

hy317 发表于 2010-4-8 13:29:29

mark

guhenggao 发表于 2010-4-8 13:38:44

mark

Swallow 发表于 2010-4-8 13:38:55

mark!

Farid 发表于 2012-5-8 21:56:16

mark不多 多谢楼主了

rantingting 发表于 2013-11-11 09:55:51

就只是PID调速吗?

josephmay 发表于 2014-6-9 19:39:34

mark~~~~~~

1ongquan 发表于 2014-6-9 20:31:37

一个标准的PID,参数都是要从串口输入的

BrightWang 发表于 2014-6-10 07:59:52

标记,我公司产品成熟使用的AVR电机控制算法

ZYBing 发表于 2014-6-10 08:22:19

mark,谢谢分享!

lzchuo 发表于 2014-6-10 10:29:51

MARK         

zzy9903 发表于 2014-6-10 11:10:19

请问,这是控制什么电机的?

qtyjwlp112a 发表于 2014-6-11 10:25:03

和张军写的《AVR系统典型开发实例》这本书里面的循迹机器人案列电机控制部分一模一样
页: [1]
查看完整版本: 我公司产品成熟使用的AVR电机控制算法