📄 mainad_usart.c
字号:
//编程时间:07-4-8~4-18
//作者:WWS /////////////////////////////////////////////////////////////////////////
/////////////////////////////利用串行口实现直流电机的调速程序////////////////////////
///基本要求如下:////////////////////////////////////////////////////////////////////
///1.////////////////////////////////////////////////////////////////////////////////
/////实现直流电机的恒电流控制,也就是说,要控制直流电机的电流恒定,实现这个任务需要//
///利用板子上的电机驱动模块、AD模块测电流,同时,还需要你看一些直流电机控制方面的资料
///2.////////////////////////////////////////////////////////////////////////////////
///将测量得到的电机相电流、速度等数据通过串行口发送出去,串行口的参数设置为:57600,/
///1起始位+8数据位+1停止位,波特率可以通过拨码开关或按键在57600或112000之间切换;//
///同时,通过串行口,用户可以设定电流值,以便于电机调节://///////////////////////////
///3.////////////////////////////////////////////////////////////////////////////////
//电机的电流或速度在数码管上显示,可通过按键切换显示内容;///////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
#include<pic.h>
/*****************************************************************************
数据定义部分
****************************************************************************/
bit ADFLAG=0,RECEFLAG=0,FUNCTION=0,UsartallowFLAG=0;
///AD中断标志位,串口数据标志位,电机在运转中标志位,串口数据存储计数值,模拟串口允许发送位
bank1 static char led[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
///////////无小数点的段码
bank1 static char led1[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
///////////有小数点的段码
bank1 static char s[4]={0,0,0,0},Saveval[9]={0,0,0,0,0,0,0,0},k;
//显示数码管服务数组,采集电压转换电流速度中间变量,循环使用值
bank1 static int elecurt,speed;
//////////显示函数调用相电流值,速度值
bank1 const char x1=0,x2=1,x3=2,x4=3;
///////////串口发送比较值
bank1 static unsigned char tab,number=0;
//////////取LED[]数组中的值用tab,键盘服务程序使用计数值number
bank1 static unsigned char key=0,RECE=0,tab;
/////////按键值,串口接收到的数据,数码管段码
bank1 static unsigned int Adresult,ADsmp,i,time;
/////////AD采样结果和当前采样值,延时函数循环值,子显示程序显示时间计数值
bank1 static unsigned char Usartallow=0,Savechar=0;
/////////发送串口数据允许位产生-时间计数值-计数到100即10S,串口发送数据允许时间计数值
/******************************************************************************
函数定义部分
****************************************************************************/
void Portinit(); //端口初始化函数
void ADinit(); //AD初始化函数
void T1inti(); //T1初始化函数
void Usartinit(); //串口初始化函数
void dis(int data); //数据拆分函数,服务于四段数码管
void speaker(char data);
void keyscan(); //键盘服务
void yw1641(char z);
void yw1642(char z);
void yw1643(char z);
void yw1644(char z);
void MOTOrun(); //电机运行控制程序
void MOTOstop(); //电机停止控制程序
void addspeed(); //电机加速控制程序
void midspeed(); //电机减速控制程序
void ChangeBAUD(); //波特率改变函数
void Saveusart();
void dealad(); //AD数据处理函数
void dealV();
void DELAY1();
void DELAY2();
void DELAY3();
/*********************************************************************
=================================主函数===============================
*********************************************************************/
void main()
{
Portinit(); //端口初试化
Usartinit(); //串口初试化
ADinit(); //AD相关寄存器初试化
T1inti(); //采样周期与发送数据至串口时间控制器T1初始化
TMR1IE=1; //打开采样时钟中断标志位
ADIE=1; //打开AD采样中断允许位
while(1)
{
/////////////////////////////////////////////////////////////////////////////////////
ChangeBAUD(); ///////拨码开关改变当前波特率 /////
////////////////当有AD采样完成则进行AD数据转化与电压转变电流速度值///////////////////
if(ADFLAG==1) ////
{ ////
dealad(); ////AD采样结果处理,送显示函数 ////
dealV(); ////处理电压值,转变为电流与速度值 ////
} ////
////////////////////////如果串口有数据发送过来///////////////////////////////////////
if(RECEFLAG==1) ////
////
{ ////
RECEFLAG=0; //清除串口接收到数据标志位 ////
switch(Saveval[Savechar]) //寻找相互匹配的串口命令 /////
{ ////
case 1 : MOTOrun(); ////
break; //当串口发来X1时,启动电机/////
case 2 : MOTOstop(); ////
break; //当串口发来X2时,停止电机/////
case 3 : addspeed(); ////
break; //当串口发来X3时,电机加速/////
case 4 : midspeed(); ////
break; //当串口发来X4时,电机减速/////
} ////
} ////
////////////////每间隔10S钟发送一次当前速度值和电流值////////////////////////////////
if(UsartallowFLAG==1) ////
{ ////
TXREG=speed; //发送当前速度值 ////
while(TRMT); //等待发送完毕 ////
TXREG=elecurt; //发送当前电流值 ////
UsartallowFLAG=0; //置允许发送位为零 ////
} ////
////////////////////////////////////显示当前电机相电流///////////////////////////////
dis(elecurt); ////
keyscan(); /////键盘扫描程序,扫描键值 ////
yw1641(s[3]); /////数码管显示函数,显示数码管第一段,显示当前电流值////
DELAY2(); ///延时函数,决定数码管显示时间,长短影响主循环和亮度////
yw1642(s[2]); //数码管显示函数,显示数码管第二段 ////
DELAY2(); ////
yw1643(s[1]); ///数码管显示函数,显示数码管第三段 ////
DELAY2(); ////
yw1644(s[0]); ///数码管显示函数,显示数码管第四段 ////
DELAY2(); ////
////////////////////////////键盘切换显示内容-显示当前速度值///////////////////////////////////
while(key==1) /////
{ /////
time++; /////
dis(speed); /////
keyscan(); /////键盘扫描程序,扫描键值 /////
yw1641(s[3]); /////显示数码管第一段,显示当前电流值 /////
DELAY2(); ///延时函数,决定数码管显示时间,长短影响主循环和亮度/////
yw1642(s[2]); //显示数码管第二段 /////
DELAY2(); /////
yw1643(s[1]); ///显示数码管第三段 /////
DELAY2(); /////
yw1644(s[0]); ///显示数码管第四段 /////
DELAY2(); /////
if(key==4|RECEFLAG==1|time>2000) break; /////
////当按键4,串口中接收到数据,执行子显示时间到都将跳出子显示循环 /////
} /////
///////////////////////////////////////////////////////////////////////////////////////////////
}
}
/**************************************************************************
初始化函数:AD初始化 void ADinit()
端口初始化 void initport()
T1初始化 void T1inti()
**************************************************************************/
void ADinit()
{
ADCON1=0x82; //转换结果右移,及ADRESH 寄存器的高6 位为"0"
ADCON0=0x55;
//10 010 000选择A/D 通道为RA2,打开A/D转换器,等待中断打开标志位ADGO
//在工作状态,且使AD 转换时钟为Fosc/8
INTCON=INTCON|0xc0;//ADGO位至1,启动AD转换
ADIF=0;
// ADON=1;
}
void Portinit()
{
ADCON1=0x07; //打开AD采集端口
TRISA=0x0f; //相应的位作为AD采集位
TRISB3=1; //按键服务位RB3
TRISD=0x00; //数码管显示服务口
TRISE=0X00; //电机驱动服务口
PORTD=0x00; //关断显示,防止电平干扰
}
void T1inti()
{ INTCON=0xc0; //打开总中断与外围中断
TMR1H=0xf3; //给T1赋值,32K晶振,计数值为0.1S
TMR1L=0x34; //给T1赋值
T1CON=0x0f; //T1为异步计数器
TMR1ON=1; //打开T1进行计数
}
void Usartinit()
{
TRISC=0X80; //设置C口方向全为输出
BRGH=1; //高速
SPBRG=21; //设置波特率为2400BPS
SYNC=0; //选择异步模式
SPEN=1; //设置串口引脚
TXEN=1; //允许串口接收
CREN=1; //允许串口发送
TXIE=0; //禁止串口发送中断
RCIE=1; //允许串口接收中断
}
/*************************************************************
中断处理函数INTinterrupt INT()
功能:处理时钟T1和AD转换
**************************************************************/
void interrupt ISR()
{
if(TMR1IF==1&&TMR1IE==1)
{
TMR1H=0xf3; //每间隔100Ms-AD采集一次
TMR1L+=0x34; //时钟计数中断则再低八位中采用加赋值,防止冲掉已经记录值
TMR1IF=0; //清除中断标志
ADON=1; //打开AD转换,次部可有可无
ADCON0=ADCON0|0x04; //中断产生后至AD标志位ADGO位为以一再次启动AD转换
Usartallow++;
if(Usartallow>100)
{
UsartallowFLAG=1;
}
}
if(ADIF==1&&ADIE==1)
{
ADIF=0;
ADFLAG=1; //AD中断完成后返回标志位,至1
}
if(RCIF&&RCIE)
{
RECEFLAG=1;
Saveusart(); //调用存储串口数据函数
}
}
/************************************************************
函数名称:void dealad()
功能: 处理AD转换的值,变为标准电压值,同时扩大1000倍
调用: 当AD采样完毕时,调用此函数
返回值: 返回AD采样结果int Adresult
*************************************************************/
void dealad()
{
ADFLAG=0;
ADsmp=ADRESL+(ADRESH<<8); //取采样结果
Adresult=((((ADsmp*50)>>6)*50)>>4)*2; //标准值Adresult=(((ADsmp*50)>>8)*10)>>2;
/*
middle[2]=Adresult/100;
middle[1]=Adresult%100/10;
middle[0]=Adresult%100%10+ Adresult%3;
*/
}
/**************************************************************
函数名称:void ChangeBAUD();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -