PIC单片机的交流电压测量C语言实例

合集下载

PIC单片机C语言编程实例一

PIC单片机C语言编程实例一
TRISC=0xD7;/*SDO引脚为输出,SCK引脚为输出*/
}
/*系统各输入输出口初始化子程序*/
voidinitial()
{
TRISA=0xDF;
TRISB=0XF0;/*设置与键盘有关的各口的数据方向*/
INTCON=0x00;/*关闭所有中断*/
data=0X00;/*待显示的寄存器赋初值*/
PORTA_5=0;/*LACK送低电平,为锁存做准备*/
}
/*SPI发送子程序*/
voidSPILED(int data)
{
SSPBUF=data;/*启动发送*/
do
{

}while(SSPIF==0);/*等待发送完毕*/
SSPIF=0;/*清除SSPIF标志*/
}
/*主程序*/
main()
{
data=table[j];/*获得需要送出显示的段码*/
RA5=0;/*LACK信号清0,为锁存做准备*/
SPILED(data);
RA5=1;/*最后给一个锁存信号,代表显示任务完成*/
}
/*中断服务程序*/
voidinterruptkeyint(void)
{
DELAY();/*软件延时*/
if ((RB5==0)||(RB4==0))/*该语句除了能够确认按键是否为干扰外,*/
}/*等待有键按下*/
DELAY();/*软件延时*/
if ((PORTB_5==0)||(PORTB_4==0))
KEYSERVE();/*如果仍有键按下,则调用键服务子程序*/
elsej=0x00;/*如果为干扰,则令返回值为0*/
return(j);
}

PIC单片机的C语言编程指南

PIC单片机的C语言编程指南

PIC单片机的C语言编程指南PIC单片机是一种常用的嵌入式系统开发平台,其具有低功耗、成本低廉、易于编程等优点,在工业自动化、电子设备控制等领域有着广泛应用。

本文将为读者提供一份PIC单片机的C语言编程指南,帮助初学者快速入门并掌握基本的编程技巧。

首先,我们需要了解一些PIC单片机的基本概念。

PIC单片机采用哈佛结构,具有多种型号和系列,每个系列有多个型号可供选择。

不同的型号和系列有不同的特性和功能,因此在编程时需要根据具体的芯片型号进行适配。

PIC单片机的编程语言常用的是C语言,其语法简洁,易于理解和学习,并且具有较高的可移植性。

在编写PIC单片机的C语言程序时,我们需要按照以下步骤进行:1. 引入头文件:使用#include指令引入所需的头文件,头文件包含了定义和声明所需的函数和变量。

3.初始化:在程序开始时对所需的资源进行初始化,包括引脚配置、中断设置、定时器初始化等。

4.主循环:编写主循环代码,其中包括需要重复执行的功能,例如读取传感器数据、处理输入输出等。

5.中断处理:根据需要,编写中断处理函数,处理外部中断、定时器中断等。

6.清理工作:在程序结束时,进行一些清理工作,例如释放资源、关闭设备等。

下面是一个PIC单片机的C语言编程示例:```c#include <xc.h> // 引入XC8编译器的头文件#define LED_PIN RC0 // 定义LED连接的引脚void iniTRISC0=0;//配置RC0引脚为输出模式void maiinit(; // 初始化while(1)LED_PIN=1;//点亮LED__delay_ms(500); // 延时500毫秒LED_PIN=0;//关闭LED__delay_ms(500); // 延时500毫秒}```上述代码实现了一个简单的功能,即使LED灯以500毫秒的间隔交替点亮和关闭。

在程序中,我们首先引入了`<xc.h>`头文件,然后定义了一个宏`LED_PIN`来表示连接LED的RC0引脚。

PIC 单片机 C 语言程序

PIC 单片机 C 语言程序

电子报/2007年/7月/15日/第015版单片机应用PIC单片机C语言程序——实例2成都立本在上一讲中,笔者对PIC单片机C语言程序作了定性介绍,其目的是使读者对C语言有所了解。

至于C语言的语法规则、程序设计方法、C编译器等内容,笔者将通过更多的C程序实例逐一介绍。

二、C语言的标识符和关键字1.C语言的标识符在C语言中所用到的文件名、函数名、变量名、数组名……,都是由字符组成的。

字符由英语字母和下划线组成,字符的组合称为C语言的标识符。

标识符是由C程序设计者自定义的。

标识符的第一个字符通常是字母,其后可以是字母或下划线,下划线可作为标识符的分段。

不同的C编译器对标识符的长度有不同的要求,在编程时定义的标识符不得超过所用编译器规定的长度,以免编译时出现错误。

在本文中,笔者介绍的C语言程序自定义的标识符不超过一个字节,在各种编译器的规范以内。

上一讲的C程序实例1中,delay、main均为C语言的标识符。

注意:同一字母的大小写,被视为不同的标识符,在设计C程序中不能混合使用。

2.C语言的关键字C语言中的关键字(又称为保留字)是C系统定义了的特定标识符,用户自定义的C标识符不能与这些关键字的字符相同,否则编译不会成功。

C语言中的关键字可分成三类:1)数据类关键字;2)程序控制类关键字;3)预处理类关键字。

C语言的主要关键字如表1所示。

三、实例2:PIC16F877的D 口(PORTD )位操作功能 C 语言程序中关键字十分重要。

为使读者有较多的感性认识,笔者通过实例2,用C 语言(包含更多的关键字)编写PIC 单片机任一口的位操作功能程序(实际上,在上一讲中,是用C 语言编写PIC 单片机任一口的字节操作功能)。

图2的示意电路是使PIC16F877(用PIC16F84A的B口同样有效)的D口,即RD0~RD3,外接的LED顺序(以秒为单位)循环点亮。

如果读者有兴趣,可在以下的C程序中添加RD4~RD7外接LED的点亮功能。

PIC单片机的C语言使用(一)

PIC单片机的C语言使用(一)

PIC单片机的C语言使用(一)在MPLAB-IDE 中使用HitechC 编译器一、装入编译器:1、启动MPLAB-IDE,如下图所示选择Project-》Install Language Toolscreen.width-300)this.width=screen.width-300” border=0>2、在弹出的安装语言工具对话框里“Language Suite”选项现在显示的是Microchip,点击后面的箭头来选择语言。

screen.width-300) this.width=screen.width-300” border=0>我使用的工具是HI-TECH PICCME,所以选择为“HI-TECH PICC”。

3、接下来在“Tool Name”里选择编译器组件的调用路径,这里有“PICC Compiler”(C 编译器)、“PICC Assembler”(汇编器)和“PICC Linker”(链接器)3 项都需要设置。

screen.width-300)this.width=screen.width-300” border=0>用“Browse”来选择调用路径,把上述3 项组件的调用文件都设为PICC.EXE。

点“OK”后完成设置。

screen.width-300)this.width=screen.width-300” border=0>二、选用编译器:1、新建一个项目,编辑项目对话框的“Language Tool Suite”栏目默认是“Microchip”,将它改为“HI-TECH PICC”。

screen.width-300)this.width=screen.width-300” border=0>2、在项目文件框里点“flasha[.hex]”,这时“Node Properties”(节点属性)按钮将会亮起来。

点击进入。

screen.width-300)this.width=screen.width-300”border=0>3、设置节点属性。

单片机数字电压表(带仿真图C程序)

单片机数字电压表(带仿真图C程序)

基于51单片机数字电压表本模块采用ADC0832模数转换芯片,LCD1602液晶显示,测量范围0-5V,精度误差0.01V看了很多网上的课程设计或者毕业论文,得出以下几点:1.数字电压表的方案有很多种,有的采用ADC0809,或者ADC0808等,他们都是8温AD,并口传输数据,具有速率高的优点。

但是硬件复杂,与单片机电路繁琐,焊接起来比较麻烦。

所以本设计采用ADC0832,同样8位AD,特点是串口传输数据,硬件接口简单,且精度误差一致,速率也比较快,对于要求不高的系统非常适合。

2.显示电路,网上采用LED显示居多,本设计采用LCD1602液晶显示,具有硬件搭设简单,显示美观等优点3.本设计方便移植,只需将LCD1602三个控制端口,ADC0832 四个控制端口修改即可。

注意LCD1602数据传输接口是单片机的P0口,如下图,需要接上拉电阻4.程序采用C代码编写,亲测直接可以使用,若需仿真文件,请用E-mail联系邮系。

邮箱:gnsywb@5.网上很多设计数据转换程序有误,不够正确。

在转换过程中,中间变量需设置为int 类型,虽然8位AD输出最高位255,但是余数转换过程中会大于255。

若设计char型,会造成显示输出有误。

void convert(uchar a){ uint temp; //特别注意这里需定义int型(余数将大于255)dis[0]=a/51; //取个位temp=a%51;temp=temp*10; dis[1]=temp/51; //取小数点后第一位temp=temp%51;temp=temp*10; dis[2]=temp/51; //取小数点后第二位}具体电路图如下:1.利用电压表与测量显示电压对比附录:C程序/******************************************** 功能:单片机数字电压表ADC0832+LCD16021,测量范围0-5V2,2路输入电压,可自行设定3,测量精度误差0.01V,LCD液晶显示编写者:小子在西藏gnsywb@编写日期:2012-11-5*********************************************/ #include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charsbit lcdrs=P2^4;sbit lcdrw=P2^5;sbit lcden=P2^6; //1602控制端口sbit DI=P3^4;sbit DO=P3^4; //DI和DO与单片机共接口sbit Clk=P3^3;sbit CS=P3^5;//ADC0832控制端口uchar dis[3]={0x00,0x00,0x00}; //显示缓冲区uchar date=0; //AD值uchar CH; //ADC0832通道值/*****************************************AD0832转换程序******************************************/uchar ADC0832(uchar CH){uchar i,dis0,dis1;Clk=0; //拉低时钟DI=1; //初始化_nop_();CS=0; //芯片选定_nop_();Clk=1; //拉高时钟_nop_();if(CH==0) //通道选择{Clk=0; //第一次拉低时钟DI=1; //通道0的第一位_nop_();Clk=1; //拉高时钟_nop_();Clk=0; //第二次拉低时钟,ADC0832 DI接受数据DI=0; //通道0的第二位_nop_();Clk=1;_nop_();}else{Clk=0;DI=1; //通道1的第一位_nop_();Clk=1;_nop_();Clk=0;DI=1; //通道1的第二位_nop_();Clk=1;_nop_();}Clk=0; //第三次拉低时钟,此前DI两次赋值决定通道DI=1; //DI开始失效,拉高电平,便于DO数据传输for(i= 0;i<8;i++) //读取前8位的值{_nop_();dis0<<= 1;Clk=1;_nop_();Clk=0;if (DO)dis0|=0x01;elsedis0|=0x00;}for (i=0;i<8;i++) //读取后8位的值{dis1>>= 1;if (DO)dis1|= 0x80;elsedis1|= 0x00;_nop_();Clk=1;_nop_();Clk=0;}if(dis0==dis1) //两次结束数据比较,若相等date=dis0; //则赋值给dat_nop_();CS=1; //释放ADC0832DO=1; //拉高输出端,方便下次通道选择DI端有效Clk=1; //拉高时钟return date;}/***********************************************数据转换程序功能:将0-255级换算成0.00-5.00的电压数***********************************************/void convert(uchar a){uint temp; //特别注意这里需定义int型(余数将大于255)dis[0]=a/51; //取个位temp=a%51;temp=temp*10;dis[1]=temp/51; //取小数点后第一位temp=temp%51;temp=temp*10;dis[2]=temp/51; //取小数点后第二位}/***************************************** LCD1602驱动程序******************************************/ void delay(uchar z){uint x,y;for(x=z;x>0;x--)for(y=122;y>0;y--);}void write_cmd(uchar cmd)//lcd1602写命令函数{lcdrs=0;lcdrw=0; //选择指令寄存器lcden=1;P0=cmd; //写数据delay(5);lcden=0; //使能拉低lcden=1;}void write_date(uchar date)//lcd1602写数据函数{lcdrs=1;lcdrw=0; //选择数据寄存器lcden=1;P0=date; //写数据delay(5);lcden=0; //使能拉低lcden=1;}void init_lcd1602()//lcd1602初始化{write_cmd(0x01); //清屏write_cmd(0x38); //功能设置write_cmd(0x0c); //显示设置write_cmd(0x06); //输入方式从左到右delay(1);}/***************************************** 显示函数*****************************************/ void display(void){uchar i;write_cmd(0x80);for(i=0;i<3;i++){if(i==1) write_date('.'); //第二位显示小数点write_date (0x30+dis[i]);delay(5);}write_date('V'); //最后一位后显示字符'V'}/************************************************ 主函数***************************************************/ void main(void){CH=0; //选择通道0或1init_lcd1602();//液晶1602显示初始化while(1) //主循环{date=ADC0832(CH);//启动ADC0832转换并接受数据delay(1);convert(date); //数据转换成BCD码display(); //显示数值}}。

一种基于PIC单片机电压采样的功率因数在线检测

一种基于PIC单片机电压采样的功率因数在线检测

一种基于PIC单片机电压采样的功率因数在线检测1.引言功率因数是交流电路中的重要参数,是衡量电力系统是否经济运行的一个重要指标,也是供电线路在线监测系统的重要检测量,在功率因数补偿系统中需对其进行实时测量[1]。

因此设计出结构简单、检测精度高的功率因数在线检测电路十分必要。

而功率因数的测量一般都要对被测电路的电压、电流进行采样,然后进行处理提取功率因数信号,通常由电压、电流取样电路、整形电路、同步周期测量、相位测量等组成,其缺点是结构较复杂,检修困难,有时会出现功率因数的测量精度不高的问题[2]。

为此,作者基于电压采样,经单片机软件进行分析、计算可得出被测电路的功率因数,通过显示电路显示出功率因数的大小,并由通信接口电路将被测功率因数进行远距离传输。

这样既简化功率因数测量电路的结构,提高功率因数的测量精度,又增强了功率因数检测电路的功能。

2.原理分析通过对电压的提取来检测功率因数的原理如图 1 (a)所示,首先采用 3 个高精度的WB 系列数字式交流电压真有效值传感器分别对被测电路的电源电压U1、附加可调电阻RP 两端电压U2 及负载电压U3 进行检测。

可调电阻RP 的作用是使附加电阻尽可能小,以减小对被测负载的影响,又可得到数值适当的电压U2 满足功率因数计算的要求。

由电路理论[3],可画出电压1、2和3的相量图如图1(b)所示,则COSϕ即是被测负载的功率因数。

500)this.style.width=500;” border=0>图 1 电压测量原理示意图与电压相量图根据几何学中的余弦定理可得,500)this.style.width=500;” border=0>由式(2)可知,只要将电压U1、U2、U3 经过运算后就可求出负载的功率因数COSϕ。

为减小测量电路的硬件开销,数据的处理与计算由单片机软件完成。

3.单片机输入输出电路设计单片机输入输出电路主要是对传感器检测。

PIC单片机的C语言

PIC单片机的C语言

㈣ volatile 修饰词 PICC 中还有一个特殊的变量修饰词“volatile”,用来 说明一个变量的值是会随机变化的,即使程序没有刻意对 它进行任何赋值操作。 在单片机中,作为输入的IO 端口其内容将是随意变 化的;很多特殊功能寄存器的值也将随着指令的运行而动 态改变。所有这种类型的变量必须将它们明确定义成 “volatile”类型,例如: volatile unsigned char STATUS @ 0x03; volatile bit commFlag;
Hitech-PICC 编译器基本上符合ANSI C标准,但是不 支持函数的递归调用。其主要原因是因为PIC 单片机特殊 的堆栈结构。PIC 单片机的堆栈是硬件实现的,其深度已 随芯片固定,无法实现需要大量堆栈操作的递归算法。
二、PICC C编译器的安装 PICC C编译器可以运行在Windows操作系统上,可 以在MPLAB IDE集成开发环境下进行项目开发。 下面介绍在MPLAB IDE 7.00集成环境下安装和设置 PICCV8.05 PL1 PICC编译器,以及在此环境下编译和调 试源程序的基本方法。

第3步:单击对话框中的Browse按钮,弹出如下图所示的 打开文件对话框。在缺省PICC V8.05PL1编译器安装目录 C:\HT-PIC\bin\下,选择plcc.exe作为编译程序。然后单击 “打开”按钮,可以发现PICC Compiler项已选择picc.exe 作为编译程序。
同样,PICC Assembler和PICC Linker都选择picc.exe 作为汇编和链接程序,如下图所示。
㈤标准库函数 PICC 提供了较完整的C 标准库函数支持,其中包括 数学运算函数和字符串操作函数。在程序中使用这些现成 的库函数时需要注意的是入口参数必须在bank0 中。 如果需要用到数学函数,则用 “#include <math.h>” 包含头文件;如果要使用字符串操作函数,就需要包含 “#include <string.h>”头文件。在这些头文件中提供了函 数类型的声明。直接查看这些头文件就可以知道PICC 提 供了哪些标准库函数。 C 语言中的格式化输出函数“printf/sprintf”用在单片 机的程序中时要特别谨慎。printf/sprintf 是一个非常大的 函数,一旦使用,你的程序代码长度就会增加很多。

交流电压测量C源程序-句句带注释

交流电压测量C源程序-句句带注释

交流电压测量程序清单该程序已在模板上调试通过,可作读者的参考。

有关显示部分请读者参考本书相关章节,有关A/D转换的详细设置请参考前面章节。

#include <pic.h>#include <math.h>#include <stdio.h>//该程序用于测电网的交流电压有效值,最后的结果将在4个LED上显示,保留//1位小数。

//为了保证调试时数据运算的精确性,需要将PICC的double型数据选成32位union adres{int y1;unsigned char adre[2];}adresult;//定义一个共用体bank3 int re[40];//定义存放A/D转换结果的数组,在bank3中unsigned char k,data;//定义几个通用寄存器double squ ,squad;//平方寄存器和平方和寄存器,squ又通用为存储其//它数值int uo;bank1 unsigned chars[4];//此数组用于存储需要显示的字符的ASII码const char table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};//不带小数点的显示段码表const char table0[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//带小数点的显示段码表//A/D转换初始化子程序void adinitial(){ADCON0=0x41;//选择A/D通道为RA0,且打开A/D转换器//在工作状态,使A/D转换时钟为8Tosc ADCON1=0X8E;//转换结果右移,及ADRESH寄存器的高6位为"0"//把RA0口设置为模拟量输入方式ADIE=1;//A/D转换中断允许PEIE=1;//外围中断允许TRISA0=1;//设置RA0为输入方式}186//spi方式显示初始化子程序void SPIINIT(){PIR1=0;SSPCON=0x30;SSPSTA T=0xC0;//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送,与"74HC595,当其//SCLK从低到高跳变时,串行输入寄存器"的特点相对应TRISC=0xD7;//SDO引脚为输出,SCK引脚为输出TRISA5=0;//RA5引脚设置为输出,以输出显示锁存信号}//系统其它初始化子程序void initial(){CCP2IE=0;//禁止CCP中断SSPIE=0;//禁止SSP中断CCP2CON=0X0B;//初始化CCP2CON,CCP2为特别事件触发方式CCPR2H=0X01;CCPR2L=0XF4;//初始化CCPR2寄存器,设置采样间隔500 μs,//一个周期内电压采40个点}//中断服务程序void interrupt adint(void){CCP2IF=0;ADIF=0;//清除中断标志adresult.adre[0]=ADRESL;adresult.adre[1]=ADRESH;//读取并存储A/D转换结果,A/D转换的结果//通过共用体的形式放入了变量y1中re[k]=adresult.y1;//1次A/D转换的结果存入数组k++;//数组访问指针加1}//SPI传送数据子程序void SPILED(data){SSPBUF=data;//启动发送do{;187}while(SSPIF==0);SSPIF=0;}//主程序main( ){adinitial();//A/D转换初始化SPIINIT();//spi方式显示初始化initial();//系统其它初始化while(1){k=0;//数组访问指针赋初值TMR1H=0X00 ;TMR1L=0X00;//定时器1清0ei();//中断允许T1CON=0X01;//打开定时器1while(1){if(k==40) break;//A/D转换次数达到40,则终止}di();//禁止中断for(k=0;k<40;k++)re[k]=re[k]-0X199;//假设提升电压为2 V,对应十六进制数199H,//则需在采样值的基础上减去该值for(k=0,squad=0;k<40;k++) {uo=re[k];squ=(double)uo;//强制把采得的数据量转换成双精度数,以便运算squ=squ*5/1023;//把每点的数据转换成实际数据squ=squ*squ;//求一点电压的平方squad=squad+squ;} //以上求得40点电压的平方和,存于寄存器squad中squ=squad/40;//求得平均值squ=sqrt(squ);//开平方,求得最后的电压值squ=squ*154.054;//通过变压器的变比和分压电阻分配确定该系数//以上得到了实际电网的电压值squ=squ*10;//为了保证显示的小数点的精度,先对电压值乘以10uo=(int)squ;//强制把U转换成有符号整型量sprintf(s,"%4d",uo);//通过sprintf函数把需要显示的电压数据转换成//ASII码,并存于数组S中RA5=0;//准备锁存for(k=0;k<4;k++){188data=s[k];data=data&0X0F;//通过按位相与的形式把ASII码转换成BCD码if(k==2) data=table0[data];//因为squ已乘以10,则需在第2位打小数点else data=table[data];// table0存储带小数点的显示段码,//table存储不带小数点的显示段码SPILED(data);//发送显示段码}for(k=0;k<4;k++) {data=0xFF;SPILED(data);//连续发送4个DARK,使显示看起来好看一些,这点与//该实验板的LED分布结构有关}RA5=1;//最后给一个锁存信号,代表显示任务完成}}各位亲,够详细吧!…………………………………………………………………..各位亲,够详细吧!…………………………………………………………………..各位亲,够详细吧!…………………………………………………………………..189各位亲,够详细吧!…………………………………………………………………..各位亲,够详细吧!…………………………………………………………………..190191。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第11章交流电压测量
11.3.2 程序清单
该程序已在模板上调试通过,可作读者的参考。

有关显示部分请读者参考本书相关章节,有关A/D转换的详细设置请参考前面章节。

#include <pic.h>
#include <math.h>
#include <stdio.h>
//该程序用于测电网的交流电压有效值,最后的结果将在4个LED上显示,保留
//1位小数。

//为了保证调试时数据运算的精确性,需要将PICC的double型数据选成32位
union adres
{
int y1;
unsigned char adre[2];
}adresult;//定义一个共用体
bank3 int re[40];//定义存放A/D转换结果的数组,在bank3中
unsigned char k,data;//定义几个通用寄存器
double squ ,squad;//平方寄存器和平方和寄存器,squ又通用为存储其
//它数值
int uo;
bank1 unsigned char s[4];//此数组用于存储需要显示的字符的ASII码
const char table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};
//不带小数点的显示段码表
const char table0[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//带小数点的显示段码表
//A/D转换初始化子程序
void adinitial()
{
ADCON0=0x41;//选择A/D通道为RA0,且打开A/D转换器
//在工作状态,使A/D转换时钟为8Tosc ADCON1=0X8E;//转换结果右移,及ADRESH寄存器的高6位为"0"
//把RA0口设置为模拟量输入方式
ADIE=1;//A/D转换中断允许
PEIE=1;//外围中断允许
186
TRISA0=1;//设置RA0为输入方式
}
//spi方式显示初始化子程序
void SPIINIT()
{
PIR1=0;
SSPCON=0x30;
SSPSTAT=0xC0;
//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送,与"74HC595,当其
//SCLK从低到高跳变时,串行输入寄存器"的特点相对应
TRISC=0xD7;//SDO引脚为输出,SCK引脚为输出
TRISA5=0;//RA5引脚设置为输出,以输出显示锁存信号
}
//系统其它初始化子程序
void i nitial()
{
CCP2IE=0;//禁止CCP中断
SSPIE=0;//禁止SSP中断
CCP2CON=0X0B;//初始化CCP2CON,CCP2为特别事件触发方式
CCPR2H=0X01;
CCPR2L=0XF4;//初始化CCPR2寄存器,设置采样间隔500 μs,
//一个周期内电压采40个点
}
//中断服务程序
void interrupt adint(void)
{
CCP2IF=0;
ADIF=0;//清除中断标志
adresult.adre[0]=ADRESL;
adresult.adre[1]=ADRESH;//读取并存储A/D转换结果,A/D转换的结果
//通过共用体的形式放入了变量y1中
re[k]=adresult.y1;//1次A/D转换的结果存入数组
k++;//数组访问指针加1
}
//SPI传送数据子程序
void SPILED(data)
{
187
SSPBUF=data;//启动发送
do{

}while(SSPIF==0);
SSPIF=0;
}
//主程序
main( )
{
adinitial();//A/D转换初始化
SPIINIT();//spi方式显示初始化
initial();//系统其它初始化
while(1){
k=0;//数组访问指针赋初值
TMR1H=0X00 ;
TMR1L=0X00;//定时器1清0
ei();//中断允许
T1CON=0X01;//打开定时器1
while(1){
if(k==40) break;//A/D转换次数达到40,则终止
}
di();//禁止中断
for(k=0;k<40;k++)re[k]=re[k]-0X199;//假设提升电压为2 V,对应十六进制数199H,
//则需在采样值的基础上减去该值
for(k=0,squad=0;k<40;k++) {
uo=re[k];
squ=(double)uo;//强制把采得的数据量转换成双精度数,以便运算
squ=squ*5/1023;//把每点的数据转换成实际数据
squ=squ*squ;//求一点电压的平方
squad=squad+squ;
} //以上求得40点电压的平方和,存于寄存器 squad中squ=squad/40;//求得平均值
squ=sqrt(squ);//开平方,求得最后的电压值
squ=squ*154.054;//通过变压器的变比和分压电阻分配确定该系数
//以上得到了实际电网的电压值
squ=squ*10;//为了保证显示的小数点的精度,先对电压值乘以10
188
uo=(int)squ;//强制把U转换成有符号整型量
sprintf(s,"%4d",uo);//通过sprintf函数把需要显示的电压数据转换成
//ASII码,并存于数组S中
RA5=0;//准备锁存
for(k=0;k<4;k++){
data=s[k];
data=data&0X0F;//通过按位相与的形式把ASII码转换成BCD码
if(k==2) data=table0[data];//因为squ已乘以10,则需在第2位打小数点
else d ata=table[data];// table0存储带小数点的显示段码,
//table存储不带小数点的显示段码
SPILED(data);//发送显示段码
}
for(k=0;k<4;k++) {
data=0xFF;
SPILED(data);//连续发送4个DARK,使显示看起来好看一些,这点与
//该实验板的LED分布结构有关
}
RA5=1;//最后给一个锁存信号,代表显示任务完成
}
}
189。

相关文档
最新文档