打印
[ZLG-MCU]

有借鉴作用,AD数据通过 串口与pc通信(转)

[复制链接]
2210|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
6019赵文|  楼主 | 2011-4-8 17:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
买了一块mega16的学习板,一直放着,今天心血来潮,做了一个小实验。利用单片机自带的AD进行电压采集,再通过串口USART将采集到的数据传输至PC机,上位机程序采用Labview对串口进行编程,读取单片机送过来的字节数据,电压换算在上位机中进行。
     单片机A/D部分较为简单,只要按照使用手册进行编程就可以了,这里读取数据时没有采用中断,而是采用查询方式,个人觉得查询方式更为常用,将AD部分做一个子程序后,在需要的时候进行调用,十分方便,但是考虑到程序执行时间,采样频率不宜太高。A/D程序如下
#include <mega16.h>
#include <delay.h>
#define uchar unsigned char
#define uint unsigned int
void Init_ADC(void)
{
    ADMUX=0x40;
    ADCSRA=0x87;
}
uint ADC(void)
{
    uint AD_value=0;
    uint temp;
    ADCSRA=ADCSRA|(1<<6);//启动一次AD转化
    while(!(ADCSRA&(1<<4)));
    ADCSRA|=1<<4;
    temp=ADCL;           //先读取低字节
    AD_value=ADCH;       //再读取高字节
    AD_value=(AD_value<<8)|temp;
    return AD_value;   
}
       通信部分只要对USART进行编程,如果采用CVAVR,它的函数库里自带有char getchar(void)void putchar(char c)(
Standard C Input/Output Functions
两个函数,其实这两个函数就是串口的驱动函数,如果不想自己变成,那么就用这两个函数吧,不过在用他们之前同样需要对串口进行必要的设置,如波特率、数据位数等。这里自己编写了串口输入输出函数。
void Put_usart(uchar data)
{
   
    while(!UCSRA.5);
    UCSRA=UCSRA|0x40;    //TCX清零
    UDR=data;
}

uchar Get_usart(void)
{
    while(!UCSRA.7); //等待RXT为1
    return UDR;
}

      实际上,在主程序中,因为串口的数据接收是随机的,不知道上位机什么时候发数据过来,就是说单片机没有主动权,所以数据接收最好采用中断,从而避免循环查询的麻烦。中断函数如下
interrupt [USART_RXC] void USART_RXC_isr(void) //USART接收中断
{
    getdata=UDR;
    Data_to_disbuf(getdata);   
}

      主程序就是每隔500ms进行一次数据采集并把采集到的数据发送至上位机
#include <mega16.h>
#include <header.h>
#include <stdio.h>

bit time_500ms_ok;
bit time_4ms_ok;

uchar time_counter;
uchar posit=0;
uchar getdata=0;

uchar dis_buff[4];
#define OE_138 PORTA.4
flash uchar Ledcode[29]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,
                         0x01,0x09};
flash uchar Bitcode[8]={0xe0,0x60,0xa0,0x20,0xc0,0x40,0x80,0x00};

void Data_to_disbuf(uint data)
{
    uchar i;
    for(i=0;i<4;i++)
    {
        dis_buff[3-i]=data%10;
        data=data/10;
    }
}
void Display(void)
{
    OE_138=0;
    Send_74HC595(Ledcode[dis_buff[posit]]);
    PORTA=(PORTA&0x1f)|Bitcode[posit];
    OE_138=1;
    if(++posit>3)
        posit=0;   
}

void main(void)
{
    uint AD_data;
    uchar AD_H,AD_L;
    TCCR0=0x0c;   //CTC模式 256分频 16000000/256*1000=0.016ms
    TCNT0=0x00;
    OCR0=0x7c;   //中断一次2ms 124+1=125*0.016=2
    TIMSK=0x02; //允许time0匹配中断
   
    DDRA=0xfe;
   
    Init_ADC();
    Init_usart();
    #asm("sei")
   
    while(1)
   
    {
   
        if(time_4ms_ok)
        {
            time_4ms_ok=0;
            //data=Get_usart();
            
            Display();
        }
        if(time_500ms_ok)
        {
            time_500ms_ok=0;
            
            AD_data=ADC();
            AD_H=AD_data>>8;
            AD_L=AD_data&0x00ff;
            Put_usart(AD_H);
            Put_usart(AD_L);
            //Data_to_disbuf(AD_data);            
        }
      
    }
}

interrupt [TIM0_COMP] void time0_comp_isr(void)     //定时器中断
{
    time_counter++;
    if(time_counter%2==0)
        time_4ms_ok=1;
    if(time_counter>=250)
    {
        time_counter=0;
        time_500ms_ok=1;
    }
}

interrupt [USART_RXC] void USART_RXC_isr(void) //USART接收中断
{
    getdata=UDR;
    Data_to_disbuf(getdata);   
}

      另一个大的方面就是上位机编程了,我只会使用Labview,幸好LV对串口进行编程还是很简单的,就不多说了,附代码先。

相关帖子

沙发
chenyelong| | 2011-4-9 08:37 | 只看该作者
没有心思看代码

使用特权

评论回复
板凳
-自己人| | 2011-4-9 19:15 | 只看该作者
avr很适合入门的一款芯片

使用特权

评论回复
地板
huzixian| | 2011-4-10 08:45 | 只看该作者
收下以后慢慢看

使用特权

评论回复
5
年轻不再| | 2011-4-20 20:23 | 只看该作者
帮顶了。

使用特权

评论回复
6
米其林r| | 2011-4-20 22:08 | 只看该作者
收下慢慢看

使用特权

评论回复
7
amini| | 2011-6-22 15:03 | 只看该作者
:(,晕。

使用特权

评论回复
8
wewo| | 2011-6-22 15:15 | 只看该作者
楼上晕啥呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

350

主题

1515

帖子

1

粉丝