实时串行数据图 [英] REAL TIME SERIAL DATA PLOT
问题描述
嗨
我希望从pic16f877a,4Mhz HS(如果给出一个正弦波输入)取样并绘制相同的图片。我给230vp正弦波50hz输入并将其转换为5v范围,并将其转换为正电压。
这是我的代码
float val,val1; //声明adcvalue存储变量
char uart_rd [50],uart_rd1 [50];
void rmsv();
void adc_uart(); // adc read and uart write
void interrupt(){
if(PIR1.ADIF){
PIR1.ADIF = 0; //清除AD中断标志
val =(ADRESH<< 8)| ADRESL; //从频道0读取爸爸
{
val1 =(val * 325.0)/1023.0;
FloatToStr(val1,uart_rd1);
strncpy(uart_rd,uart_rd1,3);
UART1_Write_Text(uart_rd1);
// UART1_Write(10);
UART1_Write(13);
delay_us(1);
}
Delay_Cyc(3); //等待获取时间
ADCON0.F2 = 1; //再次开始转换
}
}
void main()
{
TRISA = 0XFF; // porta作为输入
ADCON1 = 0x82; // AN0-> AN4被选为模拟输入
ADCON0 = 0b11000001; //配置模拟模式
INTCON.GIE = 1; //启用全局中断
INTCON.PEIE = 1; //启用外设中断
PIE1.ADIE = 1; //启用ADC中断
Delay_us(20); //等待获取时间
ADCON0.F2 = 1; //开始转换
// ADCON1 = 0X81;
UART1_Init(9600); //以9600 bps初始化UART模块
// ADC_Init();
while(1);
}
我检查了超级终端的值,看到了控制器甚至没有采样峰值电压。我希望正确地得到样本,这样我才能正确绘制波形。
好的,我看了一下在PIC16F877和ADC的数据表中是10位
我还没有检查但是我认为这条线做得对,并将高低ADC结果放在一起
val =(ADRESH<< 8)| ADRESL;
我不确定为什么你想在浮点数中使用它而不是只用16位整数运算它。当你不需要微型控制器停止玩微型控制器时它们就像瘟疫一样避开它们。
所以让我们来看看逻辑上的东西
Val是10位,所以介于0和1023之间
接下来你需要将它乘以325这样最大的数字是325x1023 = 332475
结果将适合长32位,所以我建议你将val改为long。
然后你可以进行除法,但你只是扔小数,无论如何只保留3个字符,我可以看到所以让我们重写整个批次。我确信该分区应该是10位而不是1023的1024,但我会把它留给你。
我也不能为我的生活工作为什么你想通过2个缓冲区移动字符串,你的CR和LF的尝试将无法工作:=)
尝试像
unsigned long Val;
char uart_rd [50];
....< snip> .....
Val =(ADRESH<< 8)| ADRESL; //从频道0读取爸爸
Val * = 325; //乘以Val x 325结果仍然在val(val = val * 325的简写)
Val / = 1023; // Divid Val by 1023将结果保留为val(这将截断结果)
//我保证此时Val是一个介于0-325之间的整数值,这是你想要的3位数
//现在你需要将它转换为ascii所以你可以使用ltoa或itoa编译器应该支持一个
ltoa(Val,& uart_rd [0],10); //将Val转换为基数10中的uart_rd缓冲区,换句话说,十进制
strcat(& uart_rd [0],\\\\ n); //将CR + LF添加到数字字符串
UART1_Write_Text(& uart_rd1 [0]); //现在将字符串输出串口1
....< snip> .......
标准函数的乐趣,它们的代码在网上无处不在:-)
/ * Itoa代码位于puiblic域中.. daniweb * /
char * Itoa(int value,char * str,int radix){
static char dig [] = 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ;
int n = 0,neg = 0;
unsigned int v;
char * p,* q;
if(radix == 10&& value< 0){
value = -value;
neg = 1;
}
v = value;
do {
str [n ++] = dig [v%radix];
v / = radix;
} while(v);
if(neg)str [n ++] =' - ';
str [n] ='\0';
p = str;
q = p;
while(q&& * q)++ q;
for( - q; p< q; ++ p, - q){
* p = * p ^ * q;
* q = * p ^ * q;
* p = * p ^ * q;
};
return str;
}
这是函数的简单版本之一,但只适用于基数10中的负数,这对你来说并不重要。
Hi
I wish to take the samples from pic16f877a,4Mhz HS( if it is given a sine wave input) and plot the same.I am giving 230vp sine wave 50hz as input and transformed it into 5v range and level shifted it into positive voltages.
This is my code
float val,val1;//Declare the adcvalue stored variables
char uart_rd[50],uart_rd1[50];
void rmsv();
void adc_uart();//adc read and uart write
void interrupt(){
if (PIR1.ADIF) {
PIR1.ADIF=0; // clear AD interrupt flag
val= (ADRESH << 8) | ADRESL; // read dadta from channel 0
{
val1=(val*325.0)/1023.0;
FloatToStr(val1,uart_rd1);
strncpy(uart_rd,uart_rd1,3);
UART1_Write_Text(uart_rd1);
//UART1_Write(10);
UART1_Write(13);
delay_us(1);
}
Delay_Cyc(3); //wait acquisition time
ADCON0.F2=1; //start conversion again
}
}
void main()
{
TRISA=0XFF;//porta as input
ADCON1 = 0x82; // AN0->AN4 selected as analog input
ADCON0 = 0b11000001; // Configue analog mode
INTCON.GIE = 1; //Enable global interrupt
INTCON.PEIE = 1; //Enable peripheral interrupt
PIE1.ADIE = 1; //Enable ADC interrupt
Delay_us(20); //wait for acquisition time
ADCON0.F2 = 1; //start conversion
// ADCON1=0X81;
UART1_Init(9600); // Initialize UART module at 9600 bps
//ADC_Init();
while(1);
}
I have checked the values in hyperterminal and see that the controller not even sample the peak voltage.I wish to have the samples correctly so that I can able to plot the waveform correctly.
Ok I had a quick look at the datasheet for the PIC16F877 and the ADC is 10 bit
I have not checked but I assume this line does the right thing and bring the high and low ADC results together
val= (ADRESH << 8) | ADRESL;
I am not sure why on earth you want this in a float rather than just carry it in a 16 bit integer. You are on a micro-controller stop playing with floats when you don't need they are incredibly slow on a micro avoid them like the plague.
So lets look at things logically
Val is 10 bits and so it goes between 0 and 1023
Next you need to multiply it by 325 so the largest number is 325x1023 = 332475
That result will fit into a long being 32 bits so I suggest you change val to a long.
You can then do the division but you just throw the decimals away anyhow keeping only 3 characters at end I can see so lets rewrite the whole lot. I am sure the division is supposed to be 1024 for 10 bits not 1023 but I will leave that to you.
I also can't for the life of me work out why you want to move the strings thru 2 buffers and your attempt at CR and LF will not work :=)
Try something like
unsigned long Val; char uart_rd[50]; .... <snip> ..... Val = (ADRESH << 8) | ADRESL; // read dadta from channel 0 Val *= 325; // Multiplys Val x 325 result still in val (short hand for val = val *325) Val /= 1023; // Divid Val by 1023 leave result in val (This will truncate the result) // I guarantee you at this point Val is an integer value between 0-325 which are you 3 digits you want // Now you need to convert it to ascii so you can use ltoa or itoa the compiler should support one ltoa(Val, &uart_rd[0], 10); // Convert Val into uart_rd buffer in radix base 10 in other words decimal strcat(&uart_rd[0], "\r\n"); // add CR + LF to the number string UART1_Write_Text(&uart_rd1[0]); // Now send the string out serial port 1 .... <snip> .......
The joys of standard functions the code for them is everywhere on the net :-)
/* The Itoa code is in the puiblic domain .. daniweb*/ char* Itoa(int value, char* str, int radix) { static char dig[] = "0123456789""abcdefghijklmnopqrstuvwxyz"; int n = 0, neg = 0; unsigned int v; char* p, *q; if (radix == 10 && value < 0) { value = -value; neg = 1; } v = value; do { str[n++] = dig[v%radix]; v /= radix; } while (v); if (neg) str[n++] = '-'; str[n] = '\0'; p = str; q = p; while(q && *q) ++q; for(--q; p < q; ++p, --q){ *p = *p ^ *q; *q = *p ^ *q; *p = *p ^ *q; }; return str; }
That is one of the simpler versions of the function but is only correct for negative numbers in base 10 which doesn't really matter to you.
这篇关于实时串行数据图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!