搜索
bottom↓
回复: 7

stc独立波特率发生器不工作!求助!!!

[复制链接]

出0入0汤圆

发表于 2015-5-21 14:32:54 | 显示全部楼层 |阅读模式
本帖最后由 牛东 于 2015-5-21 15:04 编辑

正在做一个无刷驱动程序,想到独立波特率发生器作串口通信,程序怎么都不成功,借鉴网上的程序也不行!!(注:用T1串口就可以)

#include<reg51.h>                //包含文件预处理命令

//-------------------------串口独立波特率发生器的特殊寄存器地址定义--------------------------------
sfr  AUXR=0x8E;          
sfr  BRT=0x9C;   
//================================================
//使用串口独立波特率发生器
void uart_init()
{
        //(注:用T1串口就可以)
        /*SCON=0x50;
        TMOD=(TMOD&0x0f)|0x20;
        TH1=TL1=0xFD; //11.0592M  9600
        TR1=1;*/

        //用此段就不行!!
        SCON=0x50;
        AUXR=0x11;
        BRT=0XFD; //11.0592M  9600
}
//=============================================                                         
void send_byte(u8 dat)
{
        SBUF=dat;
        while(!TI);  //等待TI变为1
        TI=0;   //TI清0
}
//==========================主函数===============================
void main()
{
            uart_init();
        while(1)               
        {                                                                             
                send_byte(get_ad_data(ch));
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出10入113汤圆

发表于 2015-5-21 15:18:55 | 显示全部楼层
不说STC什么型号的,寄存器地址都不同,怎么判断?

出10入113汤圆

发表于 2015-5-21 15:19:28 | 显示全部楼层
没开串口中断

出10入113汤圆

发表于 2015-5-21 15:20:47 | 显示全部楼层
ch是什么?估计楼主把很多程序删除了,这样的态度实在是无语。让别人怎么帮你?

出0入0汤圆

发表于 2015-5-21 15:44:02 | 显示全部楼层
先给BRT赋值,再AUXR=0x11;启动独立波特率发生器试试
上电延时个几十ms
while(1)               
        {                                                                             
                send_byte(get_ad_data(ch));
                //此处来点延时啦,你想把串口助手给累死啊
        }
一直发送数据,也稍微加个延时啊,有点时候是你单片机发太快了,串口助手显示不出来而已

出0入0汤圆

 楼主| 发表于 2015-5-21 16:36:43 | 显示全部楼层
饭桶 发表于 2015-5-21 15:18
不说STC什么型号的,寄存器地址都不同,怎么判断?

STC12C5410ad

出0入0汤圆

 楼主| 发表于 2015-5-21 16:38:23 | 显示全部楼层
饭桶 发表于 2015-5-21 15:20
ch是什么?估计楼主把很多程序删除了,这样的态度实在是无语。让别人怎么帮你? ...

//------------------------------------------------------
//霍尔信号采集定义W=P12 V=P11 U=P10
//-------------------------------------------------------
//状态指示灯定义 LED=P27         ABS功能选择 ABS=P26
//刹车检测口定义 shache=p34      防盗检测定义 FD=P37
//--------------------------------------------------------------------------------------------------
#include<reg51.h>                //包含文件预处理命令
sfr p2m0=0x95;                   //P2口I/Q输出模式控制位,本程序中将P2口中的6个PWM信号口设置成推挽输出
sfr p2m1=0x96;                   //P2口I/Q输出模式控制位,本程序中将P2口中的6个PWM信号口设置成推挽输出
//-------------------------AD转换要用到的特殊寄存器地址定义----------------------------------------
sfr  adc_contr=0xc5;             //定义AD转换控制寄存器地址   
sfr  adc_data=0xc6;              //定义AD转换结果寄存器地址
sfr  p1m0=0x91;                  //带有8路AD的P1口模式选择寄存器0定义地址,本程序中将带有AD转换的口设置成开漏
sfr  p1m1=0x92;                  //带有8路AD的P1口模式选择寄存器1定义地址,本程序中将带有AD转换的口设置成开漏
//-------------------------PWM=p35输出要用到的特殊寄存器地址定义---------------------------------------------
sfr  ccap1h=0xfb;                //PCA模块1捕捉/比较寄存器高8位
sfr  pca_pwm1=0xf3;              //PCA模块1-PWM寄存器
sfr  ccapm1=0xdb;                //PCA模块1工作模式寄存器
sfr  ch=0xf9;                    //PCA计数器高8位
sfr  cl=0xe9;                    //PCA计数器低8位
sfr  ccon=0xd8;                  //PCA控制寄存器
sfr  cmod=0xd9;                  //PCA工作模式寄存器
//-------------------------串口独立波特率发生器的特殊寄存器地址定义--------------------------------
sfr  AUXR=0x8E;                                  //独立波特率发生器控制寄存器
sfr  BRT=0x9C;                                         //独立波特率发生器寄存器,装初值0xfd是9600;
//------------------------------------------------------------------
typedef   unsigned char        u8;  
typedef   unsigned short int   u16;          
typedef   unsigned int         u32;
//-----------------------define PWM  regist----------------------------------
#define  PWM_ON_OFF  pca_pwm1
#define  ON    0
#define  OFF   1
#define  ERROR 1
#define  OK    0
#define  PWM_DATA                    ccap1h
#define  PWM_DISENABLE           ccapm1&=0xfd
#define  PWM_ENABLE           ccapm1|=0x02
//------------ define ADC opration const for adc_conter----------------
#define  ADC_POWER     0x80
#define  ADC_FLAG      0x10     
#define  ADC_START     0x08     
#define  ADC_SPEED     0x00   
//----------------------------IO定义----------------------------------   
sbit cr=ccon^6;                  //PCA计数器控制位,1开0关
sbit epca_lvd=IE^6;              //PCA中断允许控制位1开0关
sbit led_out=P2^7;               //指示灯
sbit alarm_out=P3^3;             //报警输出口

sbit speed_3_in=P3^1;            //3段速度控制口
sbit cruise_in=P1^4;             //巡航选择口
sbit ABS_in=P2^6;                //ABS选择口,对地为ABS功能
sbit brake_in=P3^4;              //刹车口定义,对地刹车
sbit guard_in=P3^7;              //防盗检测口

sbit  AH=P2^2;
sbit  BH=P2^1;
sbit  CH=P2^0;
sbit  AL=P2^5;
sbit  BL=P2^4;
sbit  CL=P2^3;
//========================标志位===========================
u8 led_handle_flag=0;  
u8 led_soft_start_flag=0;
u8 led_speed_flag=0;
u8 led_current_flag=0;
u8 led_hall_flag=0;          
u8 led_out_flag=0;
u8 led_run_flag=0;
u8 led_mos_flag=0;
u8 led_int0_flag=0;
u8 led_wait_flag=0;

u8 speed_timer_flag=0;                  //测量速度T0计时开始
u8 soft_start_flag=0;
u8 speed_flag=0;
//========================数据变量===========================
u8 hall_data=0;               //霍尔数据
u8 hall_data_now=0;           //霍尔新数据
u8 pwm_data=0;                //PWM值
u16 speed_count=0;             //转速数据
u8 timer_speed_count=0;       //转速检测定时器计数器
u8 second_3_block_count=0;    //3秒堵转定时计数
u8 low_voltage_count=0;       //电池欠压计数                          
u16 led_time=0;
u16 led_count=0;  
u8 led_a=0;
u8 timer0_a=0;
u8 timer0_b=0;
u8 timer0_c=0;
u8 speed_a=0;
u16 overload_count=0;

u8 hall_data_table[6]={0,0,0,0,0,0,};//霍尔数据暂存区

//============================AD转换后PWM对照表==========================================================
u8 code pwm_out_table[256]=  //实际一共256个元素
{
        1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1,  1,1,1,1,1, 1,1,1,1,1,   //0~39 0.82V以下视为转把故障        40个     
        235,235,235,235,235,  235,235,235,235,235,  //40~49视为转把归0   0.85V左右  10个有效数据           
    235,235,235,235,235,  235,235,235,235,235,  235,235,235,235,235,  235,235,235,235,235,   235,235,235,235,230,
        230,230,230,230,230,  230,230,230,230,210,  210,210,210,210,200,  200,200,200,200,200,   195,195,195,190,190,  
        190,185,185,185,180,  180,180,175,175,175,  170,170,165,165,160,  160,155,155,150,150,   145,145,140,140,135,
        135,130,130,125,125,  120,120,115,115,110,  110,105,105,100,100,  95,95,90,90,85,        85,80,80,75,75,
        70,70,65,65,60,       60,55,55,50,50,       45,45,40,40,35,       35,30,30,25,25,        20,20,15,15,10,  
        0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,        0,0,0,0,0,        0,0,0,0,0,//50~209  有效数据   0.85~3.7v         160个
        1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,         1,1,1,1,1,  1,1,1,1,1,        1,1,1,1,1, //210~250  4v以上视为转把故障 45个1
};
//=====================================================函数声明=====================================================================
void delay_ms(int t);                 void delay_us(int t);                        void all_bridge_off();          void up_bridge_on();
void down_bridge_on();                void pwm_out_on(u8 pd,u8 hd);            void pwm_out_off();                                void send_byte(u8 dat);
void system_init();                   void dispel_noise();                           void phase3_out(u8 hd);                        void int0_init();
void timer0_init();                              void pwm_init();                              void adc_init();                            void other_init();
void handle_service(u8 ch3);          void led(u8 led_number);                        void uart_init();                                void show_ADC_result(u8 ch);
                                                                                                                    
u8 get_ad_data(u8 ch);
u8 get_hall_data();
u8 speed_detect(u8 hdn);
u8 current_detect(u8 ch7);
u8 mosfet_check(u8 ch7);
u8 handle_detect(u8 ch3);
//===============================================
void system_init()
{
        other_init();
        pwm_init();
        timer0_init();
        int0_init();
        adc_init();
        uart_init();
}
//================================================
//使用串口独立波特率发生器
void uart_init()
{
        /*SCON=0x50;//mode 1,8-bit UART, enable riceve
        TMOD=(TMOD&0x0f)|0x20;//set t1 mode 2  for 8-bit auto reload   
        TH1=TL1=0xFD;//TH=TL=-(FOSC/12/32/BUND) BOUND=9600; FOSC=11.0592M
        TR1=1;*/
        SCON=0x50; //[bit6:5]SM1 SM2 = 1 0;[bit4]REN=1
        AUXR=0x11; //[bit4]BRTR=1,允许独立波特率发生器运行;[bit0]SIBRS=1,独立波特率作为串口1的波特率发生器,此时定时器1释放
        BRT=0XFD;  //独特波特率发生器定时器(产生波特率9600)
}
//=============================================                                         
void send_byte(u8 dat)
{
        SBUF=dat;
        while(!TI);  //等待TI变为1
        TI=0;   //TI清0
}
//=============================================
void show_ADC_result(u8 ch)
{
        //send_byte(ch);
        send_byte(get_ad_data(ch));       
}
//=============================================
void other_init()
{
        P1=0xff;P2=0xc0;P3=0xdf;//1101=d 3个端口初始状态
        p2m0=0xc0;p2m1=0xff;//将P2端的6个驱动口设置成强上拉推挽输出
}
//===================================================
void timer0_init()
{
        TMOD=(TMOD&0xf0)|0x01; //MODE 1,16Bit
        TH0=0x3c;TL0=0xb0;
        ET0=1;//promise interrupt
        TR0=1;//start T0
        EA=1;
}
//==============================================
void int0_init()
{
        IT0=1;EX0=1;EA=1;
}
//===============================================
void pwm_init()
{
        cmod=0x82; //PCA在空闲模式下停止PCA计数器工作,PCA时钟源为内部时钟(PSC)的1/2溢出,禁止PCA计数器溢出中断
        ccon=0x00; //禁止PCA计数器工作,清除中断标志和计数器溢出标志
        cl=0x00;ch=0x00; //计数器高低位清0
        ccapm1=0x42;//设置模块1为PWM脉冲在P35口输出
        PWM_ON_OFF=OFF;//先关闭PWM-输出为0,写入0x00就可开PWM输出
        PWM_DISENABLE;
        epca_lvd=1;EA=1;cr=1;//开PCA中断-开总中断-PCA计数器打开
}
//================================================
void adc_init()
{
        p1m0|=0xa8;p1m1|=0xa8;//设置P17-P15-P13为开漏即AD转换模式,对应电流-欠压-转把的测量
        adc_data=0x00;
        adc_contr=ADC_POWER;
        delay_ms(10);//首次开AD电源要延时1MS左右
}
//================================================
void delay_ms(int t)
{
        int i,j;
        for(i=0;i<t;i++)for(j=0;j<250;j++);
}
//================================================
void delay_us(int t)
{
        int i;
        for(i=0;i<t;i++);
}
//================================================
u8 get_ad_data(u8 ch)
{
        u8 temp;
        adc_data=0;                                                                  
        adc_contr=ADC_POWER|ADC_SPEED|ADC_START|ch;
        delay_us(5);                      
        while(!(adc_contr&ADC_FLAG));
        temp=adc_data;
        adc_contr&=(~ADC_START);                                                            
        adc_contr&=(~ADC_FLAG);
        return temp;
}
//================================================
void time0()interrupt 1
{
        TH0=0x3c;TL0=0xb0;//50ms 11.0592MHz
        //---------以下为重负载低速计时----------------
        if(speed_timer_flag==1)overload_count++;       
        else overload_count=0;        
        //---------以下为LED处理-----------------------
        if(led_out_flag)
        {
                if(led_a==1)
                {
                        timer0_a++;
                        if(timer0_a>=led_time)            
                        {       
                                led_out=~led_out;timer0_b++;timer0_a=0;
                                if(timer0_b>=led_count){timer0_b=0;led_a=0;}
                        }
                }
                else //灭灯间隔
                {
                        led_out=1;timer0_c++;
                        if(timer0_c>=20){timer0_c=0;led_a=1;}
                }       
        }
        else{timer0_a=0;timer0_b=0;timer0_c=0;}
}                           
//=====================================================
void int0()interrupt 0
{  
        pwm_out_off();       
        led(7);
}
//======================================================
void pwm_out_on(u8 pd,u8 hd)  
{
        PWM_DATA=pd; //写入经AD转换后的转把PWM数据
        PWM_ON_OFF=ON;//PWM输出
        phase3_out(hd);
}
//=======================================================
void pwm_out_off()
{
        PWM_ON_OFF=OFF;
        all_bridge_off();
}
//=======================================================
u8 get_hall_data()
{
        u8 temp,hall_fault_flag;
        u8 i,j;
        i=P1&0x07;delay_us(5);j=P1&0X07; //2次读入霍尔数据
        if(i-j){hall_fault_flag=1;}
        else
        {
                temp=j;
                //----------霍尔120度,查是否全1和全0-----------------
                if((temp==0x07)||(temp==0x00)){hall_fault_flag=1;}
                else {hall_fault_flag=0;hall_data_now=temp;}                          
        }
        return         hall_fault_flag;       
}

//=========================输出相序============================
//AL,BL,CL,AH,BH,CH===P2.5~P2.0   P2.6==ABS  P2.7==LED
//入口:霍尔数据 hall_data
//出口:输出节拍:a+b-,c+b-,c+a-,b+a-,b+c-,a+c-
//对应hall_data:  101  001        011         010  110  100
//==============================================================
void phase3_out(u8 hd)
{
          switch(hd)
        {
                 case 1: {AL=0;BL=1;CL=0;AH=0;BH=0;CH=1;} break;//c+b-   
                case 2: {AL=1;BL=0;CL=0;AH=0;BH=1;CH=0;} break;//b+a-   
                case 3: {AL=1;BL=0;CL=0;AH=0;BH=0;CH=1;} break;//c+a-       
                case 4: {AL=0;BL=0;CL=1;AH=1;BH=0;CH=0;} break;//a+c-       
                case 5: {AL=0;BL=1;CL=0;AH=1;BH=0;CH=0;} break;//a+b-       
                case 6: {AL=0;BL=0;CL=1;AH=0;BH=1;CH=0;} break;//b+c-
        }                               
}
//===================================================
void all_bridge_off()
{
        AH=0;BH=0;CH=0;AL=0;BL=0;CL=0;
}
//===================================================
void up_bridge_on()
{
        AH=1;BH=1;CH=1;
}
//===================================================
void down_bridge_on()
{
        AL=1;BL=1;CL=1;
}
//==============电机速度测量函数 ====================
u8 speed_detect(u8 hdn)
{
        u8 speed_lower_flag=0;
        u8 i=0,result=0;       
        if(speed_a<6)
        {               
                hall_data_table[speed_a]=hdn;
                speed_a++;
        }
        else if(speed_a==6)
        {
                speed_a=0;
                for(i=0;i<6;i++){result=(result+hall_data_table);}
                if(result==21)//转子15对极,转一圈霍尔输出15个周期,数字21为一个周期的三相霍尔数据和
                {
                           result=0;
                        speed_count++;//霍尔周期数累加                                                
                        speed_timer_flag=1;        //50ms计时开始标志置1                
                        if(overload_count==200)//2S延时到
                        {       
                                overload_count=0;
                                 speed_timer_flag=0;       
                                //转子15对极,转一圈霍尔输出15个周期,600r/min即10圈/s,即150周期/s,
                                //实际转速折算的周期值比程序中的周期值要大,可能其他程序有消耗时间
                                if(speed_count<350)        //2s300个周期,电机750r/min折算到程序没有187T/s,可能只有150T/s
                                {
                                        speed_lower_flag=1;                                               
                                        speed_count=0;
                                }
                                else{speed_lower_flag=0;}                                                                
                        }
                }        
        }
        return speed_lower_flag;                                               
}
//====================================================================
//函数:平均电流检测限流函数                                          
//入口:LM358第7脚的电流经AD转换后的值   
//出口:供PWM调整占空比值
u8 current_detect(u8 ch7)
{
        u8 temp,over_current_flag=0;
        temp=get_ad_data(ch7);
        if(temp>40){over_current_flag=1;}//358放大倍数约4倍,康铜20m欧 ,10A的电流temp值40
        else {over_current_flag=0;}
        return over_current_flag;                                                                    
}
//======================================================================
u8 mosfet_check(u8 ch7)
{
        u8 mosfet_check_flag=0;
        //-------------------上桥测试-----------------------
        down_bridge_on();
        PWM_DATA=0x00; //全开占空比
        PWM_ON_OFF=ON;
        if(get_ad_data(ch7)>2){mosfet_check_flag=1;}//上桥MOS管有故障       
        else{mosfet_check_flag=0;}
        //------------关输出延时防上下桥短路 ---------------
        pwm_out_off();
        delay_us(5);     
        //-------------------下桥测试-----------------------
        up_bridge_on();                                  
        PWM_DATA=0x00;
        PWM_ON_OFF=ON;         
        if(get_ad_data(ch7)>2){mosfet_check_flag=1;}//上桥MOS管有故障       
        else{mosfet_check_flag=0;}
        pwm_out_off();
        return mosfet_check_flag;                                  
}                                                                                       
//=========================把手AD值检测=================================
void handle_service(u8 ch3)
{
        u8 i=0,j=0;
        u8 max_data=20;
        u8 min_data=255;
        u8 temp=0;
        temp=get_ad_data(ch3);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
        if((temp<40)||(temp>200)){led(2);PWM_DISENABLE;}//0.8v以下或3.8v以上,有故障                                                    
        else
        {
                if((temp>40)&&(temp<45)){led(1);PWM_DISENABLE;}//待机
                else if(temp>45){PWM_ENABLE;led(8);}//运行
                pwm_data=pwm_out_table[temp];
                while(current_detect(7)==ERROR){led(3);pwm_out_off();}
                while(get_hall_data()==ERROR){led(6);pwm_out_off();}
                pwm_out_on(pwm_data,hall_data_now);       
                if(temp>170)//3V对应AD值150,3.9V对应AD值200
                {
                        if(hall_data_now!=hall_data)
                        {        
                                hall_data=hall_data_now;                                          
                                if(speed_detect(hall_data)==ERROR){while(1){led(5);pwm_out_off();}}                                                                                                                                   
                        }               
                }                                                                                                           
        }                                                             
}                                                                            
//=========================led函数==============================
// 闪1次=待机
// 闪2次=转把未归0或AD值不正常                                     
// 闪3次=358放大电路检测到电流参数不对或有开路情况
// 闪4次=输出MOS有故障                 
// 闪5次=电机堵转保护后停止
// 闪6次=电机相序不对或霍尔损坏        
// 闪7次=358比较器检测到电流过大保护(外部中断)
// 快闪=工作
void led(u8 led_number)
{
        switch(led_number)
        {
                case 0:{led_out_flag=0;led_count=0;led_time=0;}break;
                case 1:{led_out_flag=1;led_count=2;led_time=4;}break;
                case 2:{led_out_flag=1;led_count=4;led_time=4;}break;
                case 3:{led_out_flag=1;led_count=6;led_time=4;}break;
                case 4:{led_out_flag=1;led_count=8;led_time=4;}break;
                case 5:{led_out_flag=1;led_count=10;led_time=20;}break;
                case 6:{led_out_flag=1;led_count=12;led_time=4;}break;
                case 7:{led_out_flag=1;led_count=14;led_time=4;}break;
                case 8:{led_out_flag=1;led_count=50000;led_time=1;}break;
        }
}
//==========================主函数===============================
void main()
{
    system_init();
        while(mosfet_check(7)==ERROR){pwm_out_off();led(4);}
        while(1)               
        {                                                                            
                 handle_service(3);         
                show_ADC_result(3);
                //show_ADC_result(7);
        }
}

出0入0汤圆

 楼主| 发表于 2015-5-21 16:43:39 | 显示全部楼层
大米饭 发表于 2015-5-21 15:44
先给BRT赋值,再AUXR=0x11;启动独立波特率发生器试试
上电延时个几十ms
while(1)               

//------------------------------------------------------
//霍尔信号采集定义W=P12 V=P11 U=P10
//-------------------------------------------------------
//状态指示灯定义 LED=P27         ABS功能选择 ABS=P26
//刹车检测口定义 shache=p34      防盗检测定义 FD=P37
//--------------------------------------------------------------------------------------------------
#include<reg51.h>                //包含文件预处理命令
sfr p2m0=0x95;                   //P2口I/Q输出模式控制位,本程序中将P2口中的6个PWM信号口设置成推挽输出
sfr p2m1=0x96;                   //P2口I/Q输出模式控制位,本程序中将P2口中的6个PWM信号口设置成推挽输出
//-------------------------AD转换要用到的特殊寄存器地址定义----------------------------------------
sfr  adc_contr=0xc5;             //定义AD转换控制寄存器地址   
sfr  adc_data=0xc6;              //定义AD转换结果寄存器地址
sfr  p1m0=0x91;                  //带有8路AD的P1口模式选择寄存器0定义地址,本程序中将带有AD转换的口设置成开漏
sfr  p1m1=0x92;                  //带有8路AD的P1口模式选择寄存器1定义地址,本程序中将带有AD转换的口设置成开漏
//-------------------------PWM=p35输出要用到的特殊寄存器地址定义---------------------------------------------
sfr  ccap1h=0xfb;                //PCA模块1捕捉/比较寄存器高8位
sfr  pca_pwm1=0xf3;              //PCA模块1-PWM寄存器
sfr  ccapm1=0xdb;                //PCA模块1工作模式寄存器
sfr  ch=0xf9;                    //PCA计数器高8位
sfr  cl=0xe9;                    //PCA计数器低8位
sfr  ccon=0xd8;                  //PCA控制寄存器
sfr  cmod=0xd9;                  //PCA工作模式寄存器
//-------------------------串口独立波特率发生器的特殊寄存器地址定义--------------------------------
sfr  AUXR=0x8E;                                  //独立波特率发生器控制寄存器
sfr  BRT=0x9C;                                         //独立波特率发生器寄存器,装初值0xfd是9600;
//------------------------------------------------------------------
typedef   unsigned char        u8;  
typedef   unsigned short int   u16;          
typedef   unsigned int         u32;
//-----------------------define PWM  regist----------------------------------
#define  PWM_ON_OFF  pca_pwm1
#define  ON    0
#define  OFF   1
#define  ERROR 1
#define  OK    0
#define  PWM_DATA                    ccap1h
#define  PWM_DISENABLE           ccapm1&=0xfd
#define  PWM_ENABLE           ccapm1|=0x02
//------------ define ADC opration const for adc_conter----------------
#define  ADC_POWER     0x80
#define  ADC_FLAG      0x10     
#define  ADC_START     0x08     
#define  ADC_SPEED     0x00   
//----------------------------IO定义----------------------------------   
sbit cr=ccon^6;                  //PCA计数器控制位,1开0关
sbit epca_lvd=IE^6;              //PCA中断允许控制位1开0关
sbit led_out=P2^7;               //指示灯
sbit alarm_out=P3^3;             //报警输出口

sbit speed_3_in=P3^1;            //3段速度控制口
sbit cruise_in=P1^4;             //巡航选择口
sbit ABS_in=P2^6;                //ABS选择口,对地为ABS功能
sbit brake_in=P3^4;              //刹车口定义,对地刹车
sbit guard_in=P3^7;              //防盗检测口

sbit  AH=P2^2;
sbit  BH=P2^1;
sbit  CH=P2^0;
sbit  AL=P2^5;
sbit  BL=P2^4;
sbit  CL=P2^3;
//========================标志位===========================
u8 led_handle_flag=0;  
u8 led_soft_start_flag=0;
u8 led_speed_flag=0;
u8 led_current_flag=0;
u8 led_hall_flag=0;          
u8 led_out_flag=0;
u8 led_run_flag=0;
u8 led_mos_flag=0;
u8 led_int0_flag=0;
u8 led_wait_flag=0;

u8 speed_timer_flag=0;                  //测量速度T0计时开始
u8 soft_start_flag=0;
u8 speed_flag=0;
//========================数据变量===========================
u8 hall_data=0;               //霍尔数据
u8 hall_data_now=0;           //霍尔新数据
u8 pwm_data=0;                //PWM值
u16 speed_count=0;             //转速数据
u8 timer_speed_count=0;       //转速检测定时器计数器
u8 second_3_block_count=0;    //3秒堵转定时计数
u8 low_voltage_count=0;       //电池欠压计数                          
u16 led_time=0;
u16 led_count=0;  
u8 led_a=0;
u8 timer0_a=0;
u8 timer0_b=0;
u8 timer0_c=0;
u8 speed_a=0;
u16 overload_count=0;

u8 hall_data_table[6]={0,0,0,0,0,0,};//霍尔数据暂存区

//============================AD转换后PWM对照表==========================================================
u8 code pwm_out_table[256]=  //实际一共256个元素
{
        1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1,  1,1,1,1,1, 1,1,1,1,1,   //0~39 0.82V以下视为转把故障        40个     
        235,235,235,235,235,  235,235,235,235,235,  //40~49视为转把归0   0.85V左右  10个有效数据           
    235,235,235,235,235,  235,235,235,235,235,  235,235,235,235,235,  235,235,235,235,235,   235,235,235,235,230,
        230,230,230,230,230,  230,230,230,230,210,  210,210,210,210,200,  200,200,200,200,200,   195,195,195,190,190,  
        190,185,185,185,180,  180,180,175,175,175,  170,170,165,165,160,  160,155,155,150,150,   145,145,140,140,135,
        135,130,130,125,125,  120,120,115,115,110,  110,105,105,100,100,  95,95,90,90,85,        85,80,80,75,75,
        70,70,65,65,60,       60,55,55,50,50,       45,45,40,40,35,       35,30,30,25,25,        20,20,15,15,10,  
        0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,        0,0,0,0,0,        0,0,0,0,0,//50~209  有效数据   0.85~3.7v         160个
        1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,  1,1,1,1,1,         1,1,1,1,1,  1,1,1,1,1,        1,1,1,1,1, //210~250  4v以上视为转把故障 45个1
};
//=====================================================函数声明=====================================================================
void delay_ms(int t);                 void delay_us(int t);                        void all_bridge_off();          void up_bridge_on();
void down_bridge_on();                void pwm_out_on(u8 pd,u8 hd);            void pwm_out_off();                                void send_byte(u8 dat);
void system_init();                   void dispel_noise();                           void phase3_out(u8 hd);                        void int0_init();
void timer0_init();                              void pwm_init();                              void adc_init();                            void other_init();
void handle_service(u8 ch3);          void led(u8 led_number);                        void uart_init();                                void show_ADC_result(u8 ch);
                                                                                                                    
u8 get_ad_data(u8 ch);
u8 get_hall_data();
u8 speed_detect(u8 hdn);
u8 current_detect(u8 ch7);
u8 mosfet_check(u8 ch7);
u8 handle_detect(u8 ch3);
//===============================================
void system_init()
{
        other_init();
        pwm_init();
        timer0_init();
        int0_init();
        adc_init();
        uart_init();
}
//================================================
//使用串口独立波特率发生器
void uart_init()
{       
        /*
        SCON=0x50;//mode 1,8-bit UART, enable riceve
        TMOD=(TMOD&0x0f)|0x20;//set t1 mode 2  for 8-bit auto reload   
        TH1=TL1=0xFD;//TH=TL=-(FOSC/12/32/BUND) BOUND=9600; FOSC=11.0592M
        TR1=1;*/

        SCON=0x50; //[bit6:5]SM1 SM2 = 1 0;[bit4]REN=1
        BRT=0XFD;  //独特波特率发生器定时器(产生波特率9600)
        AUXR=0x11; //[bit4]BRTR=1,允许独立波特率发生器运行;[bit0]SIBRS=1,独立波特率作为串口1的波特率发生器,此时定时器1释放
        delay_ms(100);
}
//=============================================                                         
void send_byte(u8 dat)
{
        SBUF=dat;
        while(!TI);  //等待TI变为1
        TI=0;   //TI清0
}
//=============================================
void show_ADC_result(u8 ch)
{
        //send_byte(ch);
        send_byte(get_ad_data(ch));       
}
//=============================================
void other_init()
{
        P1=0xff;P2=0xc0;P3=0xdf;//1101=d 3个端口初始状态
        p2m0=0xc0;p2m1=0xff;//将P2端的6个驱动口设置成强上拉推挽输出
}
//===================================================
void timer0_init()
{
        TMOD=(TMOD&0xf0)|0x01; //MODE 1,16Bit
        TH0=0x3c;TL0=0xb0;
        ET0=1;//promise interrupt
        TR0=1;//start T0
        EA=1;
}
//==============================================
void int0_init()
{
        IT0=1;EX0=1;EA=1;
}
//===============================================
void pwm_init()
{
        cmod=0x82; //PCA在空闲模式下停止PCA计数器工作,PCA时钟源为内部时钟(PSC)的1/2溢出,禁止PCA计数器溢出中断
        ccon=0x00; //禁止PCA计数器工作,清除中断标志和计数器溢出标志
        cl=0x00;ch=0x00; //计数器高低位清0
        ccapm1=0x42;//设置模块1为PWM脉冲在P35口输出
        PWM_ON_OFF=OFF;//先关闭PWM-输出为0,写入0x00就可开PWM输出
        PWM_DISENABLE;
        epca_lvd=1;EA=1;cr=1;//开PCA中断-开总中断-PCA计数器打开
}
//================================================
void adc_init()
{
        p1m0|=0xa8;p1m1|=0xa8;//设置P17-P15-P13为开漏即AD转换模式,对应电流-欠压-转把的测量
        adc_data=0x00;
        adc_contr=ADC_POWER;
        delay_ms(10);//首次开AD电源要延时1MS左右
}
//================================================
void delay_ms(int t)
{
        int i,j;
        for(i=0;i<t;i++)for(j=0;j<250;j++);
}
//================================================
void delay_us(int t)
{
        int i;
        for(i=0;i<t;i++);
}
//================================================
u8 get_ad_data(u8 ch)
{
        u8 temp;
        adc_data=0;                                                                  
        adc_contr=ADC_POWER|ADC_SPEED|ADC_START|ch;
        delay_us(5);                      
        while(!(adc_contr&ADC_FLAG));
        temp=adc_data;
        adc_contr&=(~ADC_START);                                                            
        adc_contr&=(~ADC_FLAG);
        return temp;
}
//================================================
void time0()interrupt 1
{
        TH0=0x3c;TL0=0xb0;//50ms 11.0592MHz
        //---------以下为重负载低速计时----------------
        if(speed_timer_flag==1)overload_count++;       
        else overload_count=0;        
        //---------以下为LED处理-----------------------
        if(led_out_flag)
        {
                if(led_a==1)
                {
                        timer0_a++;
                        if(timer0_a>=led_time)            
                        {       
                                led_out=~led_out;timer0_b++;timer0_a=0;
                                if(timer0_b>=led_count){timer0_b=0;led_a=0;}
                        }
                }
                else //灭灯间隔
                {
                        led_out=1;timer0_c++;
                        if(timer0_c>=20){timer0_c=0;led_a=1;}
                }       
        }
        else{timer0_a=0;timer0_b=0;timer0_c=0;}
}                           
//=====================================================
void int0()interrupt 0
{  
        pwm_out_off();       
        led(7);
}
//======================================================
void pwm_out_on(u8 pd,u8 hd)  
{
        PWM_DATA=pd; //写入经AD转换后的转把PWM数据
        PWM_ON_OFF=ON;//PWM输出
        phase3_out(hd);
}
//=======================================================
void pwm_out_off()
{
        PWM_ON_OFF=OFF;
        all_bridge_off();
}
//=======================================================
u8 get_hall_data()
{
        u8 temp,hall_fault_flag;
        u8 i,j;
        i=P1&0x07;delay_us(5);j=P1&0X07; //2次读入霍尔数据
        if(i-j){hall_fault_flag=1;}
        else
        {
                temp=j;
                //----------霍尔120度,查是否全1和全0-----------------
                if((temp==0x07)||(temp==0x00)){hall_fault_flag=1;}
                else {hall_fault_flag=0;hall_data_now=temp;}                          
        }
        return         hall_fault_flag;       
}

//=========================输出相序============================
//AL,BL,CL,AH,BH,CH===P2.5~P2.0   P2.6==ABS  P2.7==LED
//入口:霍尔数据 hall_data
//出口:输出节拍:a+b-,c+b-,c+a-,b+a-,b+c-,a+c-
//对应hall_data:  101  001        011         010  110  100
//==============================================================
void phase3_out(u8 hd)
{
          switch(hd)
        {
                 case 1: {AL=0;BL=1;CL=0;AH=0;BH=0;CH=1;} break;//c+b-   
                case 2: {AL=1;BL=0;CL=0;AH=0;BH=1;CH=0;} break;//b+a-   
                case 3: {AL=1;BL=0;CL=0;AH=0;BH=0;CH=1;} break;//c+a-       
                case 4: {AL=0;BL=0;CL=1;AH=1;BH=0;CH=0;} break;//a+c-       
                case 5: {AL=0;BL=1;CL=0;AH=1;BH=0;CH=0;} break;//a+b-       
                case 6: {AL=0;BL=0;CL=1;AH=0;BH=1;CH=0;} break;//b+c-
        }                               
}
//===================================================
void all_bridge_off()
{
        AH=0;BH=0;CH=0;AL=0;BL=0;CL=0;
}
//===================================================
void up_bridge_on()
{
        AH=1;BH=1;CH=1;
}
//===================================================
void down_bridge_on()
{
        AL=1;BL=1;CL=1;
}
//==============电机速度测量函数 ====================
u8 speed_detect(u8 hdn)
{
        u8 speed_lower_flag=0;
        u8 i=0,result=0;       
        if(speed_a<6)
        {               
                hall_data_table[speed_a]=hdn;
                speed_a++;
        }
        else if(speed_a==6)
        {
                speed_a=0;
                for(i=0;i<6;i++){result=(result+hall_data_table);}
                if(result==21)//转子15对极,转一圈霍尔输出15个周期,数字21为一个周期的三相霍尔数据和
                {
                           result=0;
                        speed_count++;//霍尔周期数累加                                                
                        speed_timer_flag=1;        //50ms计时开始标志置1                
                        if(overload_count==200)//2S延时到
                        {       
                                overload_count=0;
                                 speed_timer_flag=0;       
                                //转子15对极,转一圈霍尔输出15个周期,600r/min即10圈/s,即150周期/s,
                                //实际转速折算的周期值比程序中的周期值要大,可能其他程序有消耗时间
                                if(speed_count<350)        //2s300个周期,电机750r/min折算到程序没有187T/s,可能只有150T/s
                                {
                                        speed_lower_flag=1;                                               
                                        speed_count=0;
                                }
                                else{speed_lower_flag=0;}                                                                
                        }
                }        
        }
        return speed_lower_flag;                                               
}
//====================================================================
//函数:平均电流检测限流函数                                          
//入口:LM358第7脚的电流经AD转换后的值   
//出口:供PWM调整占空比值
u8 current_detect(u8 ch7)
{
        u8 temp,over_current_flag=0;
        temp=get_ad_data(ch7);
        if(temp>40){over_current_flag=1;}//358放大倍数约4倍,康铜20m欧 ,10A的电流temp值40
        else {over_current_flag=0;}
        return over_current_flag;                                                                    
}
//======================================================================
u8 mosfet_check(u8 ch7)
{
        u8 mosfet_check_flag=0;
        //-------------------上桥测试-----------------------
        down_bridge_on();
        PWM_DATA=0x00; //全开占空比
        PWM_ON_OFF=ON;
        if(get_ad_data(ch7)>2){mosfet_check_flag=1;}//上桥MOS管有故障       
        else{mosfet_check_flag=0;}
        //------------关输出延时防上下桥短路 ---------------
        pwm_out_off();
        delay_us(5);     
        //-------------------下桥测试-----------------------
        up_bridge_on();                                  
        PWM_DATA=0x00;
        PWM_ON_OFF=ON;         
        if(get_ad_data(ch7)>2){mosfet_check_flag=1;}//上桥MOS管有故障       
        else{mosfet_check_flag=0;}
        pwm_out_off();
        return mosfet_check_flag;                                  
}                                                                                       
//=========================把手AD值检测=================================
void handle_service(u8 ch3)
{
        u8 i=0,j=0;
        u8 max_data=20;
        u8 min_data=255;
        u8 temp=0;
        temp=get_ad_data(ch3);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
        if((temp<40)||(temp>200)){led(2);PWM_DISENABLE;}//0.8v以下或3.8v以上,有故障                                                    
        else
        {
                if((temp>40)&&(temp<45)){led(1);PWM_DISENABLE;}//待机
                else if(temp>45){PWM_ENABLE;led(8);}//运行
                pwm_data=pwm_out_table[temp];
                while(current_detect(7)==ERROR){led(3);pwm_out_off();}
                while(get_hall_data()==ERROR){led(6);pwm_out_off();}
                pwm_out_on(pwm_data,hall_data_now);       
                if(temp>170)//3V对应AD值150,3.9V对应AD值200
                {
                        if(hall_data_now!=hall_data)
                        {        
                                hall_data=hall_data_now;                                          
                                if(speed_detect(hall_data)==ERROR){while(1){led(5);pwm_out_off();}}                                                                                                                                   
                        }               
                }                                                                                                           
        }                                                             
}                                                                            
//=========================led函数==============================
// 闪1次=待机
// 闪2次=转把未归0或AD值不正常                                     
// 闪3次=358放大电路检测到电流参数不对或有开路情况
// 闪4次=输出MOS有故障                 
// 闪5次=电机堵转保护后停止
// 闪6次=电机相序不对或霍尔损坏        
// 闪7次=358比较器检测到电流过大保护(外部中断)
// 快闪=工作
void led(u8 led_number)
{
        switch(led_number)
        {
                case 0:{led_out_flag=0;led_count=0;led_time=0;}break;
                case 1:{led_out_flag=1;led_count=2;led_time=4;}break;
                case 2:{led_out_flag=1;led_count=4;led_time=4;}break;
                case 3:{led_out_flag=1;led_count=6;led_time=4;}break;
                case 4:{led_out_flag=1;led_count=8;led_time=4;}break;
                case 5:{led_out_flag=1;led_count=10;led_time=20;}break;
                case 6:{led_out_flag=1;led_count=12;led_time=4;}break;
                case 7:{led_out_flag=1;led_count=14;led_time=4;}break;
                case 8:{led_out_flag=1;led_count=50000;led_time=1;}break;
        }
}
//==========================主函数===============================
void main()
{
    system_init();
        while(mosfet_check(7)==ERROR){pwm_out_off();led(4);}
        while(1)               
        {                                                                            
                 handle_service(3);         
                show_ADC_result(3);
                //show_ADC_result(7);
        }
}

回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 08:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表