基于ARM嵌入式温度控制原型系统的设计1温度控制应用的总体介绍一般的计算机的过程控制系统的主要流程是周期性地采集A/D中的模拟量,然后比较给定量和采样值,把差值通过一些控制算法(PID控制)进行数据处理,处理结果经过D/A变换将数字信号转换成模拟信号,然后输出到执行机构,从而对被控对象进行控制。针对计算机控制系统的特点,本文设计的温度闭环控制系统如下图1-1所示:图1-1温度闭环控制系统结构其主要流程是在手动状态下对AD通道中的模拟量周期采集,采样值经过socket上传服务器,同时服务器等待发控制字,然后系统接收到控制字,并通过DA转换进而在标准信号控制相应设备输出;在自动状态下对AD通道的模拟量周期采集,把给定值和采样值进行比较,对差值进行控制算法处理,然后得到计算结果,该结果通过DA转换成相应的模拟量,然后由标准信号输出,根据上述功能所要求来编写应用程序。本设计中没有服务器端程序的设计,客户端的应用程序主要有main(主程序)、AD数据采集程序、DA数据接收程序、数据读取程序,温度控制报警和灯亮程序等几个部分。、2主要的应用程序实现主程序函数主要是起到一个创建子程序并监视子程序运行情况的作用,如果子进程不能运行,则该进程重新创建需要重新创建;如果要安装信号,主进程在退出时应该向子进程传递发出一个终止信号,以处理一些收尾的工作。主程序关键函数:voidmain(){tmp_data=ds18b20_fun();if(tmp_data50){open_buzzer();::system(kill-sSTOP`pidofled-player`);printf(\nBUZZERPWMControl\n);printf(Press'ESC'keytoExitthisprogram\n\n);printf( %2d.%d℃\n,tmp_data/10,tmp_data%10);}elseprintf( 85.0℃\n);}主程序的流程图1-2所示:图1-2主程序流程图2.1DS18B20驱动程序设计本文设计选用的是主芯片为Samsung公司的S3C2440的mini2440开发板为硬件平台,软件平台是Linux的最新内核Linux2.6.29。通过mini2440的扩展接口引出GPIO口(GPBl)为数据线DQ。由于DS18B20为单总线器件,所以它对操作的时序比较严格。正确地编写复位程序、位写程序和位读程序,对于DS18B20驱动最终能否正常运行并且得到实时的温度值,起到很关键的作用。开始ARM系统初始化初始化ds18b20跳过ROM温度转化跳过ROM等待转化完成再次初始化ds18b20读取温度跳过ROM温度转化主程序灯灭灯亮或者温度报警控制输出温50C结束NY恢复正常2.2DS18B20读写函数unsignedshortds18b20_fun(void){intfd;intret;floattemp;unsignedshortdata;fd=open(/dev/TX2440-ds18b20,0);if(fd0){perror(opendeviceds18b20);exit(1);}ret=read(fd,&data,4);if(ret0)printf(readds18b20error\n);returndata;close(fd);}if(strncmp(buf,$FLAG1$,7)==0){tmp_data=ds18b20_fun();tmp_temp=tmp_data*0.0625;tmp_data=tmp_temp*10+0.5;if(tmp_data1000)printf( %2d.%d℃\n,tmp_data/10,tmp_data%10);elseprintf( 85.0℃\n);}2.3复位程序一般我们在对DS18B20进行读写之前时,首先应该对其复位程序的初始化,从而检测DS18B20是否存在。复位时,我们一般要求通过MCU把数据线下拉480~960μs,然后再释放数据线,大约等待60μs左右。如果MCU接收到DS18B20发出的数据显示是低电平,那么表示复位成功。复位函数程序如下#defineDQS3C2440_GPB1#defineDQ_INPUTS3C2440_GPB1_INP#defineDQ_OUTPUTS3C2440_GPB1_OUTPUTvoidreset(){do{S3C2440_gpio_cfgpin(DQ,DQ_OUTPUT);S3C2440_gpio_setpin(DQ,1);udelay(1);S3C2440_gpio_setpin(DQ,0);udelay(600);S3C2440_gpio_setpin(DQ,1);udelay(60);}While((S3C2440_gpio_getpin(DQ))!=0);While((S3C2440_gpio_getpin(DQ))==0);}2.4写1字节子程序发送ROM和RAM指令,需向DS18B20写入数据。写1字节子程序如下:voidwritebyte(ucharcomd){uchari;S3C2440_gpio_cfgpin(DQ,DQ_OUTPUT)for(i=o;i8;i++){S3C2440_gpio_setpin(DQ,0)udelay(1)if(comd&0x01)S3C2440_gpio_setpin(DQ,1)udelay(65)S3C2440_gpio_setpin(DQ,1)comd=comd1;}2.5读N字节子程序如果温度转换完毕,则需要进入DS18B20的RAM中读取第0和第1字节的二进制数据。读1字节的子程序如下:ucharreadbyte(void){uchari,temp=0;for(i=0;i8;i++){temp1;S3C2440_gpio_cfgpin(DQ,DQ_OUTPUT);S3C2440_gpio_setpin(DQ,0);udelay(1);S3C2440_gpio_setpin(DQ,1);S3C2440_gpio_cfgpin(DQ,DQ_INPUT);udelay(10);if(S3C2440_gpio_getpin(DQ)){temp=(temp︱0x80);udelay(65);S3C2440_gpio_cfgpin(DQ,DQ_OUTPUT);S3C2440_gpio_setpin(DQ,1);}return(temp);}}读取N字节的子程序如下:voidreadnbyte(ucharN,Uchar*temp){uchari;for(i=0;iN;i++){*temp=readbyte();temp++;}}本文采用模块加载的方法来调试DS18B20的驱动程序2.6A/D数据采集程序功能与实现.一般在工业生产中不需要很高的采集频率,当通过A/D程序采集数据时,采集通道一般设置为每隔1秒钟采集一次,然后按照接收模式来确定采用手动或者自动模式,并把采集到的数据写入或D/A共享内存或者A/D共享内存中。如果通道无法采集时,一般程序会通过调用非阻塞的:eleet()函数来解决这个问题,这样就避免了浪费系统资源和系统阻塞的问题。A/D程序流程如下图1-3所示【15】。图1-3A/D程序流程图函数关键部分实现如下:if((fd=open(”/dev/ADS7842”,O_WRONLY))==-l){Perror(“openADCerror!!\n”):exit(l);}while(l){fs_sel=seleet(fd+1,NULL,&fs-Write,NULL,&tv_timeout):if(fs_sel){//读AD通道值result=write(fd,&CHA,sizeof(unsignedint));初始化共享内存读取A/D通道值读socket共享内存存模式转化写D/A共享内存写A/D共享内存手动自动A/D控制算法if(result0){Printf(“WriteADChannelError!\n”);Retum-1;}value=(((float)result)/4096)*5.0;Prinif(“CH%d=%fV\n”,CHA,value);Read_share_SOCKET()://读soeket共享内存GetMode(szBuf_SOCKET,mode);if((*mode)==“AA”){AD_data=gcvt(value,4,AD_data);write_share_AD(CHA,AD_data);写AD共享内存}elseif((*mode)==“MM”){Control_ALG(res,value);//控制算法Write_Share_DA(CHA,res);写DA共享内存}else{Printf(“Findmodecharerror!\n”);Continue;}}}2.7D/A数据采集程序功能与实现在确定自动或者手动模式后,D/A数据采集程序会决定读取数据包的路径:DA共享内存或者socket共享内存,D/A的程序流程图如下图1-4所示【15】。图1-4D/A程序流程图函数关键部分实现如下:while(1){Read_Share_SOCKET()://读soeket共享内存GetMode(szBuf_SOCKET,mode);if((*mode)==“AA”){Read_share_DA();//AUTO:读DA共享内存GetData(szBuf_DA,RecvPack);DA_data=atof(ReevPack);}elseif((*mode)===”MM”)//MANUAL:读soeket共享内存{D/A初始化共享内存读socket共享内存读D/A共享内存读socket共享内存模式转换自动手动GetData(szBuf_SOCKET,RecvPack)://取DA数据包DA_data=atof(RecvPack);}elsecontinue;if((fd=oPen(“/dev/DAC712”,O_WRONLY))==-l){Perror(“openDACerror”);exit(1):}rev=write(fd,&DA_data,sizeof(DA_data));close(dafd);}2.8温度控制报警主函数实现intmain(intargc,char**argv){intfreq=1000;inttmp_data;floattmp_temp;if(tmp_data50){tmp_data=ds18b20_fun();tmp_temp=tmp_data*0.0625;tmp_data=tmp_temp*10+0.5;open_buzzer();printf(\nBUZZERPWMControl\n);printf(Press'ESC'keytoExitthisprogram\n\n);printf( %2d.%d℃\n,tmp_data/10,tmp_data%10);}elseprintf( 85.0℃\n);}通过linux交叉编译程序,并成功没错误如下图1-5界面所示:图1-5交叉编译界面即得到可执行文件然后挂载到开发板上,执行命令#./pwm蜂鸣器会响2.9温度灯控主要函数实现intmain(void){inttmp_data;floattmp_temp;tmp_data=ds18b20_fun();tmp_temp=tmp_data*0.0625;tmp_data=tmp_temp*10+0.5;if(tmp_data50){::system(kill-sSTOP`pidofled-player`);m_fd=::open(/dev/leds0,O_RDONLY);if(m_fd0){m_fd=::open(/dev/leds,O_RDONLY);}printf(&