原创 【ATMEGA16L】实验二八:USART综合实验

2009-8-14 09:40 4372 4 6 分类: MCU/ 嵌入式

》》点此进入      http://bbs.armavr.com/   ARM-AVR嵌入式开发论坛


【相关实验】


实验一:流水灯实验(八种LED点亮模式)


实验二:有源蜂鸣器驱动实验


实验三:按键扫描(用KEY选择对应LED点亮)


实验四:键盘扫描+8种LED亮灭模式控制


实验二四:四线制LCD1602B驱动实验        


实验二五:八线制LCD1602B驱动实验


*********************************************************************


        2008年年末,初步的学习了AVR单片机的USART模块(实验20),现在看来,当时的理解不深入不全面,没能从抓住它的要点。今天从新的复习了一下,详细的阅读了datasheet,感觉收益颇深,之前不能理解的概念,今天突然的明了了。看来:“书读百遍,其意自现”的古语真是有道理啊。


        本次的综合实验,参考了www.avrvi.com的部分程序。现在分享出来,供朋友们参考,希望朋友们多提意见,批评指正。


一、硬件电路


1、LED电路


53e5c5ff-f702-4d41-a6c3-911aa825ac15.jpg


2、MAX232电路


点击看大图


3、串口调试助手数据接收


0fd3272e-c3a4-422c-ad9a-e96a9da938ae.jpg


二、程序结构


1d122155-9c09-4dbb-90b2-053fe670969e.jpg


三、程序代码


1、main.c主函数


/******************************************************************************
Platform: AVR mega16学习板(www.iccavr.com
Project : 实验二八:USART综合实验
Clock F : 3.6864MHz
Software: ICCAVR7.14C
Author  : 林夕依然
Version : 09.03.19
Updata  :
comments:
1、以学习板LED,MAX232为硬件电路。
2、接收发自电脑的数据,根据收到的对应数据,先将收到的数据原样返回电脑,并执行
   收到的数据所对应的操作。
3、用串口助手工具调试,理解串口通讯协议。
4、两种串口初始化方法均可使用。
5、参考:AVR与虚拟仪器 http://www.avrvi.com 古欣AVR mega16 串口测试
problem :
1、一个汉字有两个字节组成
2、使用USART_Transmits02(*a) 函数时,电脑接收乱码
*******************************************************************************/
// ICC-AVR application builder : 2007-5-20 17:21:25
// Target : M16
// Crystal: 3.6864Mhz
// AVR mega16 串口测试
// AVR与虚拟仪器 http://www.avrvi.com 古欣


#include <iom16v.h>
#include <macros.h>


const unsigned char buffer[]="2009年03月19日23:55";
const unsigned char buffer1[]="QQ:605987969";
const unsigned char buffer2[]="欢迎访问http://blog.ednchina.com/xiantaozeng/";


void main(void)
{
 unsigned char i="0",tmp=0;


 port_init();           //端口初始化,关闭LED
 //Usart_init01();      //初始化串口方式1,波特率9600 (测试可用)
 Usart_init02(9600);    //初始化串口方式2,波特率9600  (测试可用)
 
 for(i=0;i<20;i++)      //发送数组里面的字符串:实验日期和时间
 {
   USART_Transmit(buffer);
 }
  newline();//换行
 
 while(1)
 {
  if(UCSRA&(1<<RXC))    //如果接收缓存区有数据
  {
   tmp="USART"_Receive(); //接收数据
   USART_Transmit(tmp); //发送数据
  
   if(tmp=='a')         //对接收到的数据进行,如果是a,再发一个OK回来
   {
    newline();//换行
    USART_Transmit('O');
 USART_Transmit('K');
 newline();//换行
   }
   if(tmp=='A')          //对接收到的数据进行,如果是A,再发一个Hello回来
   {
    newline();//换行
    USART_Transmits01();
 newline();//换行
   }
   if(tmp=='q'|tmp=='Q') //检测接收到的数据,如果是q或Q,则将QQ号码返回给电脑
   {
     newline();//换行
     for(i=0;i<12;i++)   //发送数组里面的字符串
     {
     USART_Transmit(buffer1);
     }
  newline();//换行
   }
   if(tmp=='w'|tmp=='W') //检测接收到的数据,如果是w或W,则将EDN博客网址发给电脑
   {
     newline();//换行
     for(i=0;i<45;i++)  //发送数组里面的字符串:http://blog.ednchina.com/xiantaozeng/
     {
     USART_Transmit(buffer2);
     }
  newline();//换行
   }  
   if(tmp=='1')         //如果接收到的数据是1,第1种LED模式运行
   {
    blank();//空格
    led01();
   }
   if(tmp=='2')         //如果接收到的数据是2,第2种LED模式运行
   {
    blank();//空格
    led02();
   }
   if(tmp=='3')         //如果接收到的数据是3,第3种LED模式运行
   {
    blank();//空格
    led03();
   }
   if(tmp=='4')         //如果接收到的数据是4,第4种LED模式运行
   {
    blank();//空格
    led04();
   }
   if(tmp=='5')         //如果接收到的数据是5,第5种LED模式运行
   {
    blank();//空格
    led05();
   }
   if(tmp=='6')         //如果接收到的数据是6,第6种LED模式运行
   {
    blank();//空格
    led06();
   }
   if(tmp=='7')         //如果接收到的数据是7,第7种LED模式运行
   {
    blank();//空格
    led07();
   }
  }
 }
}


2、function.c功能函数


#include <iom16v.h>
#include <macros.h>


#define F_CPU 3686400
/************************************************
  UMSEL  模式选择
    0    异步操作
    1    同步操作


  USBS 停止位位数
    0     1
    1     2


  UCSZ2 UCSZ1 UCSZ0 字符长度
    0     0     0     5 位
    0     0     1     6 位
    0     1     0     7 位
    0     1     1     8 位
    1     0     0     保留
    1     0     1     保留
    1     1     0     保留
    1     1     1     9 位
*************************************************/
void Usart_init01(void)              //初始化串口方式1
{
  UCSRA="0X02";  //倍速选择
  UCSRB=(1<<RXEN)|(1<<TXEN);  //使能接收,发送
  UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8bit,异步,无奇偶校验,1个停止位
  UBRR="47"; //9600波特率,见M16_cn中文P155:Table68-72通用振荡器频率下设置 UBRR                    
}


void Usart_init02( unsigned int baud )//初始化串口方式2,并设置波特率
{
unsigned int tmp;
tmp= F_CPU/baud/16-1;      //设置波特率,见M16_cn中文P135:Table60波特率计算公式
UBRRH = (unsigned char)(tmp>>8);
UBRRL = (unsigned char)tmp;
UCSRB = (1<<RXEN)|(1<<TXEN); //接收器与发送器使能
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);//帧格式:8个数据位,2个停止位
}


//下面两个函数直接从数据手册上拷贝过来的


// 数据发送【发送5 到8 位数据位的帧】
void USART_Transmit( unsigned char data )
{
while ( !( UCSRA & (1<<UDRE)) ) ;  //等待发送缓冲器为空
UDR = data;                        // 将数据放入缓冲器,发送数据
}


// 数据接收【以5 到8 个数据位的方式接收数 据帧】
unsigned char USART_Receive( void )
{
while ( !(UCSRA & (1<<RXC)) );  // 等待接收数据
return UDR;                     // 从缓冲器中获取并返回数据
}


//连续发送字符
void USART_Transmits01( void )
{
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'H';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'e';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'l';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'l';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'o';
}


//以下是字符串的操作:
void USART_Transmits02(unsigned char *ptr)//字符串
{
   while (*ptr)
   {
       USART_Transmit(*ptr);
       *ptr++;
   }
   newline();
}


void newline()   //换行
{
   USART_Transmit(0x0d);  //发送一个回车
   USART_Transmit(0x0a);  //发送一个换行
}


void blank()    //空格
{
   USART_Transmit(0x20); 
}


3、led.c LED函数


/*******************************
Platform : AVR mega16学习板(www.iccavr.com
function :功能函数集
Clock F  : 3.6864M
Software : ICCAVR7.14C
Author   : 林夕依然
Version  : 09.02.25
comments :
********************************/
#include <iom16v.h>
#include <macros.h>


void port_init()
{
  DDRB =0XFF;
  PORTB="0XFF";
}


void LED_on()                            //打开所有LED
    {
 PORTB =0X00;
 DelayMs(100);
 } 
 
void LED_off()                           //关闭所有LED
    {
 PORTB = 0xFF;
 DelayMs(100); 
 }


void LED_01(int i)                  //LED亮灭控制
    {
    PORTB = ~BIT(i);                //输出低电平
    DelayMs(100);                   //调用延时程序
    }
 
void LED_02(int i)                  //间隔点亮
    {
 PORTB=~(BIT(i)|BIT(i-2));
 DelayMs(100);
 }
 
void LED_03(int i)                 //相临点亮
    {
 PORTB=~(BIT(i)|BIT(i-1));      //~后内容需用括号括起来
 DelayMs(100);
 }
 
void LED_04(int i)                 //发散聚集点亮
    {
 switch(i)
  {
  case 0:PORTB=0xE7;DelayMs(100);break;    //延时100ms
  case 1:PORTB=0xDB;DelayMs(100);break;
  case 2:PORTB=0xBD;DelayMs(100);break;
  case 3:PORTB=0x7E;DelayMs(100);break;
  default:break;
  }
 }
 
void LED_05(int i)                 //00,0F,F0,FF方式显示
    {
 switch(i)
  {
  case 0:PORTB=0x00;DelayMs(100);break;    //延时100ms
  case 1:PORTB=0x0F;DelayMs(100);break;
  case 2:PORTB=0xF0;DelayMs(100);break;
  case 3:PORTB=0xFF;DelayMs(100);break;
  default:break;
  }
 }
 
void LED_06(int i)
   {
   switch(i)
    {
 case 0:PORTB=0XAA;DelayMs(100);break;
 case 1:PORTB=0X55;DelayMs(100);break;
 }
   }


//8种不同的点亮模式
void led01()          //模式1:顺序点亮
    {
      unsigned char h="5",i;
  
      while(h--)
     {
        for (i = 0; i < 8; i++)     //顺序单个点亮LED
        LED_01(i);
        for (i = 6; i > 0; i--)     //逆序单个点亮LED
        LED_01(i);
  PORTB=0XFF;
     }
    }
   
void led02()         //模式2:间隔点亮
    {
      unsigned char h="5",i;
      while(h--)
      {
        for (i = 2; i < 8; i++)     //间隔顺序同时点亮
        LED_02(i);
        for (i = 6; i > 2; i--)  //间隔逆序同时点亮
        LED_02(i);
  PORTB=0XFF;
      }
    }
   
void led03()         //模式3:相临点亮
    {
      unsigned char h="5",i;


      while(h--)
      {
        for (i = 1; i < 8; i++)     //相临顺序同时点亮
        LED_03(i);
        for (i = 6; i > 1; i--)  //相临逆序同时点亮
        LED_03(i);
  PORTB=0XFF;
      }
    }  
   
void led04()       //模式4:发散聚集点亮
    {
      unsigned char h="5",i;


      while(h--)
      {
        for(i=0;i<4;i++)            //发散点亮
        LED_04(i);
        for(i=2;i>0;i--)            //聚集点亮
        LED_04(i);  
  PORTB=0XFF;  
      }
    }
   
void led05()         //模式5:四四点亮
    {
      unsigned char h="5",i;


      while(h--)
      {
        for(i=0;i<4;i++)            //四四顺序点亮
        LED_05(i);
        for(i=2;i>0;i--)            //四四逆序点亮
        LED_05(i); 
  PORTB=0XFF;   
      }
    }
   
void led06()        //模式6:四四点亮
    {
      unsigned char h="5",i;


      while(h--)
      {
        for(i=0;i<2;i++)            //四四顺序点亮
        LED_06(i); 
  PORTB=0XFF; 
      }
    }
   
void led07()         //模式7:全部点亮熄灭
    {
      unsigned char h="5";
      while(h--)
     {
        LED_on();
        LED_off();
     }
  PORTB="0XFF";
    }


4、delay.c延时函数


/*******************************
Platform : AVR mega16学习板(www.iccavr.com
function :延时函数
Clock F  : 3.6864M
Software : ICCAVR7.14C
Author   : 林夕依然
Version  : 09.02.25
comments :
1、两种方式实现延时
********************************/


/*---------------------------------------------------------------------------------
     延时程序计算方法
     计数个数j = 延时时间/6*晶振频率 - 1
---------------------------------------------------------------------------------*/


#define uchar unsigned char
#define uint unsigned int


//方式一:
void Delay()                       
    {
    uchar a, b, c;
    for (a = 1; a; a++)
        for (b = 1; b; b++)
            for (c = 0; c<10; c++)  //循环次数=255*255*10
          ;
    }


//方式二:1ms延时,准确性较Delay();高
void DelayMs(uint i)               
   {
    while(i--)
    {                         
     uint j;               
        for(j=1;j<=613;j++)  
      ;              
    }                      
   }


 

文章评论2条评论)

登录后参与讨论

用户160973 2010-11-28 21:46

谢谢了

tengjingshu_112148725 2009-3-23 09:24

学习啦
相关推荐阅读
用户1400544 2012-09-24 08:55
【分享】ATmega16学习笔记PDF完整版下载(WinAVR)
  笔记均为原创,欢迎转载,转载请注明出处!   笔记1:8种LED点亮模式_GCC.pdf 笔记2:有源蜂鸣器驱动实验_GCC.pdf 笔记3:按键扫描(用KEY选择对应LED...
用户1400544 2011-01-19 23:26
博主邀请您:加入千脑,拥有“我的在线电脑”
点击加入千脑,拥有“我的在线电脑”在线电脑随时随地可用,安全可靠您可能遇到以下情况: 用户场景一:        我是一个集团公司的企业白领,经常负责写些策划书,制作各类表格等,有时候上班时间做不完就...
用户1400544 2010-04-07 00:43
ATmega16_Basic_V1.1范例2:8种LED点亮模式(ICC)
一、程序结构二、程序源码1、main.c /******************************************************************************...
用户1400544 2010-04-07 00:22
ATmega16_Basic_V1.1范例1:LED流水灯(ICC)
一、程序结构二、程序源码1、main.c /******************************************************************************...
用户1400544 2010-03-30 14:39
Altium Designer 6原理图元件库大全(7个种类)
》》点此进入      http://bbs.armavr.com/   ARM-AVR嵌入式开发论坛       ARM-AVR嵌入式开发论坛推出【Altium Designer 6 原理图元件库大...
用户1400544 2010-03-30 14:39
protel99原理图元件库大全(8个种类)
》》点此进入      http://bbs.armavr.com/   ARM-AVR嵌入式开发论坛       ARM-AVR嵌入式开发论坛推出【protel99原理图元件库大全(8个种类)】,共...
我要评论
2
4
关闭 站长推荐上一条 /2 下一条