文章归档友情连接照片地图

电动车自动档位控制

分类:电子设计  作者:rming  时间:2012-12-03

好久好久,没状态,事情乱七八糟,想想原因,被动的原因多,不喜欢被动,不喜欢受约束,不喜欢被事情牵着走,可是这个年纪没办法了,只能去适应了。

电动车自动档位控制

主要考虑电动机电流过载和转速,测试版代码

/#include<stc12c2052ad.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
/*Define ADC operation const for ADC_CONTR*/
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDLL 0x00 //420 clocks
#define ADC_SPEEDL 0x20 //280 clocks
#define ADC_SPEEDH 0x40 //140 clocks
#define ADC_SPEEDHH 0x60 //70 clocks
void delay_ms(uint i);
void InitUart();
void SendData(uchar dat);
void SendString( uchar *str);
void init_adc();
uchar get_adc();
void show_adc_result(uchar adc_result);
uchar t1count,timecount;
bit flag;	//计时结束标志位
unsigned long f,t; //频率,转速
uchar level;//档位
void main()
{
//变量初始化
uchar temp_i=0;
t1count=0;
timecount=0;
flag=0;
f=0;
t=0;
level=1;
//串口、AD初始化
InitUart(); //Init UART, use to show ADC result
init_adc(); //Init ADC sfr
while(1){
//200A/5V 8位AD
temp_i=(get_adc()*200/256);
show_adc_result(temp_i);
//1秒计时结束,计算脉冲频率
if(flag==1){
flag=0;//清除标志位
//计算频率/Hz
f=t1count*65536+TH1*256+TL1;
//电动机一转4Hz
//计算转速 r/min
t=f/4/60;
}
//情况1(转速大于2000转,电流小于100A === 换二档)
if(t>2200&&temp_i<100&&level==1){
level=2; //设置二档标志
P3&=0xbb;//Y0开
P3|=0x08 //Y1断
}elseif(t>2200&&temp_i>100&&level==2){//情况2(无视转速、电流过载、档位2 === 换一档)
level=1; //设置一档标志位
P3|=0x04;//Y0断
P3&=0xb7 //Y1开
}
/*
继电器操作
P3&=0x9f//Y3开
P3&=0xaf //Y2开
P3&=0xb7 //Y1开
P3&=0xbb //Y0开
*/
}
}
//P3.5脉冲输入
//定时器0工作方式1 16位定时,定时器1方式1 做外部中断计数
void t0t1_init(){
AUXR &= 0x7F;	//定时器时钟12T模式
TMOD=0x51;//T1方式1外部中断计数,T0方式1 16位定时
TH1=0;
TL1=0;
//T0定时50ms一次中断,20次中断即获取1s计时
TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
//启动T0、T1
TR1=1;
TR0=1;
ET0=1;
ET1=1;
EA=1;
}
//T0定时
void t0(void)interrupt 1 using 0
{
//12T模式下 50ms
TL0 = 0x00;	//设置定时初值
TH0 = 0x4C;	//设置定时初值
timecount++;
if(timecount>=20){ //计时1s结束
//暂停T1脉冲计数
TR1=0;
//计时清零
timecount=0;
//1s计时结束
flag=1;
}
}
//T1外中断计数	P3.5
void t1(void)interrupt 3 using 0
{
t1count++;
}
void show_adc_result(uchar adc_result)
{
uchar temp[5];
temp[0]=(uint)adc_result/100+0x30;
adc_result=(uint)adc_result%100;
temp[1]=((uint)adc_result)/10+0x30;
temp[2]=((uint)adc_result)%10+0x30;
temp[3]='\r';
temp[4]='\n';
SendString(temp);
}
//AD转换初始化 ----打开ADC电源
void init_adc()
{
P1=0xff;
ADC_CONTR|=0x80;
delay_ms(80);
P1M0=0x10;//这两个寄存器用来设置 P1口四种状态,每一位对应一个P1引脚 ,按状态组合操作
P1M1=0x10;//设置P1.1为开漏状态
}
uchar get_adc()
{
ADC_DATA = 0; //清除结果
ADC_CONTR = 0x60; //转换速度设置 0x60 最快速度
ADC_CONTR = 0xE0; //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位
ADC_CONTR |= 0x04; //选择 A/D 当前通道 P1.4
delay_ms(1); //使输入电压达到稳定
ADC_CONTR |= 0x08; //0000,1000 令 ADCS = 1, 启动A/D转换,
while (1) //等待A/D转换结束
{
if (ADC_CONTR & 0x10) //0001,0000 测试A/D转换结束否
{ break; }
}
ADC_CONTR &= 0xE7; //1111,0111 清 ADC_FLAG 位, 关闭A/D转换,
return ADC_DATA; //返回 A/D 8 位转换结果
}
/*----------------------------
延时函数
----------------------------*/
void delay_ms(uint i)	//@11.0592MHz
{
uint j;
_nop_();
j = 2090;
do
{
while (--j);
} while (--i);
}
//串口初始化
void InitUart( void )
{
/*
//脉冲计数需要用两个计数器,取消串口方式1,不用定时器1,改用串口方式2
SCON = 0x50 ; //SCON: serail mode 1, 8-bit UART, enable ucvr
TMOD |= 0x20 ; //TMOD: timer 1, mode 2, 8-bit reload
PCON |= 0x00 ; //SMOD=0;
TH1 = 0xFD ; //Baud:9600 fosc=11.0592MHz
IE |= 0x90 ; //Enable Serial Interrupt
TR1 = 1 ; // timer 1 run
// TI=1;
*/
SCON = 0X90;//9位UART,波特率为 Fosc/64 串口方式2
PCON |= 0x00 ; //SMOD=0;	波特率 172800.9 hz
IE |= 0x90 ; //Enable Serial Interrupt
}
//向串口发送一个字符
void SendData( unsigned char ch)
{
SBUF=ch;
while (TI== 0 );
TI= 0 ;
}
//向串口发送一个字符串,strlen为该字符串长度
void SendString( unsigned char *str)
{
while (*str) //检测字符串结束标志
{
SendData(*str++); //发送当前字符
}
}


  1. Vincent Ting Vincent Ting

    参观来了- -准备也折腾下~

提交评论