实时串行数据图 [英] REAL TIME SERIAL DATA PLOT

查看:115
本文介绍了实时串行数据图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我希望从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆