搜索
bottom↓
回复: 17

10.1长假结束,决定用一个月做马潮老师讲义上的主要实验。

[复制链接]

出0入0汤圆

发表于 2007-10-7 19:52:52 | 显示全部楼层 |阅读模式
第一个实验:设计一个4种闪烁方式交替循环的彩灯,闪烁方式见图6-7。

(实验要求见讲义第6章的第9页,简记为P6-9,以后引用讲义内容均按此标记)

源代码:
/*********************************************
Writer:wjyspring
file name                         : demo_6_9.c
Chip type           : ATmega16
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*********************************************/

#include <mega16.h>
#include <delay.h>
//#include <math.h>   
  #include <stdlib.h>   
void main(void)
{   
char i=0;
char position = 0;        // position为控制位的位置

PORTA=0xFF;        // PA口输出全1,LED全灭
DDRA=0xFF;                  // PA口工作为输出方式
              
while(1)
{
  for(i=0;i<16;i++)                   //左移循环两轮
  {
        PORTA = ~(0x80>>position);                       
        if (++position >= 8) position = 0;
        delay_ms(500);
  }   
  for(i=0;i<16;i++)                    //右移循环两轮
  {
        PORTA = ~(1<<position);               
        if (++position >= 8) position = 0;
        delay_ms(500);
  }  
   for(i=0;i<16;i++)                    //间隔点亮明暗交替16次
  {
        PORTA = 0xaa;               
        delay_ms(500);
        PORTA = ~0xaa;               
        delay_ms(500);
  }   
  for(i=0;i<16;i++)     //随机点亮16次
  {
        PORTA =rand();
        delay_ms(500);
  }     
}
}

关于rand和srand函数的说明:rand的内部实现是用线性同余法做的,它不是真的随机数,只不过是因为其周期特别长,所以有一定的范围里可看成是随机的,rand()会返回一随机数值,范围在0至RAND_MAX 间。在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。rand()产生的是假随机数字,每次执行时是相同的。若要不同,以不同的值来初始化它.初始化的函数就是srand()。

请菜鸟思考,在这个实验要求中(见讲义),我们并不需要用到srand函数。这是为什么?呵呵。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2007-10-7 20:20:52 | 显示全部楼层
第二个实验:讲义P6-15,控制一个8段数码管循环显示“0”-“F”16个十六进制的数字,每个字符显示1秒钟,并且在显示的1秒内,数码管的小数点(P段)要亮0.5s,灭0.5s。

源代码:
/*********************************************   
writer              :wjyspring  
file name                 :demo_6_15.c
Chip type           : ATmega16
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*********************************************/

#include <mega16.h>
#include <delay.h>

flash char led_7[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
                      0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
bit point_on = 1;
void main(void)
{
        char i = 0;

        PORTA=0xFF;
        DDRA=0xFF;

        while (1)
    {
                for (i=0;i<=15;i++)
                {
                        PORTA = led_7;
                        if (point_on) PORTA |= 0x80;
                        delay_ms(500);        
                        point_on = ~point_on;   
                         PORTA = led_7;
                        if (point_on) PORTA |= 0x80;  
                        delay_ms(500);  
                        point_on = ~point_on;  
                }
               
    };
}

出0入0汤圆

发表于 2007-10-7 23:14:25 | 显示全部楼层
另外建议你把我的例程后面的问题与思考仔细想想,然后把答案贴上来,大家讨论。

出0入0汤圆

发表于 2007-10-8 01:44:52 | 显示全部楼层
给新人一些建议.

在大家编程之前,先去看看华为公司的软件编程规范,网上很容易看到的.

最起码我看到上面的软件例子的时候就感觉蛮便扭的.

简单看了两眼,不像出自一个单片机软件高人的手笔.变量命名规则有待改进.char之类的和编译器有关的东西没有用宏,等等.
还有好几处不合适的地方,我就不指出了.

虽然大家会认为这只是个小实验,随便点无所谓.

但一个在软件上有些资历的人编程会有一些风格的,其实只要有一点点地和自己风格不一样的地方,都会让自己非常的不舒服.一定会改掉的,所以我们基本能从简单的一小段代码中看出一个人对程序的理解度,和写程序的实力,更能看出一个人的阅历.

出0入0汤圆

发表于 2007-10-8 02:06:25 | 显示全部楼层
一个资深的软件设计师形成的5个阶段:

1: 入门阶段: 读大量的程序,能够自己修改和拼凑出一个能实现功能的程序. 可以完成简单的软件工作.
2: 合格阶段: 熟知各种知名的程序风格,形成自己的风格,并能够独立完成一个超过1W行代码的项目,基本无错误.
3: 优秀阶段: 熟读各种系统内核源码,能够正确评判代码的质量,效率,优缺点. 十分考究冗余性,扩展性,纠错性等,能够在大型软件项目中担任核心成员.
4: 核心阶段: 能够自己编写出优秀操作系统之类内核源码,能够带领团队完成大型软件工程.
5: 专家阶段: 可以有创立一种更加优秀的软件思想的专家.能够权威并且正确无误的批判所有软件质量的专家.

出0入0汤圆

发表于 2007-10-8 09:26:38 | 显示全部楼层
同意3楼,养成良好的习惯有时候比掌握一门技术更重要,尤其对初学者

出0入0汤圆

 楼主| 发表于 2007-10-8 09:26:41 | 显示全部楼层
感谢以上两位的指教!
做第三个实验P6-17例6.5 六位LED数码管动态扫描控制显示设计(一)出现了点问题。。。用马老师的代码昨天晚上能够从时间初始值23:58:55正常运行,今天再做的时候6个数码管显示全为“0”,2个小数点位还在每隔1秒闪烁。怀疑数码管坏了,重做第2个实验,结果正常。不知道问题在哪儿。


出0入0汤圆

 楼主| 发表于 2007-10-8 15:03:03 | 显示全部楼层
第3个实验的问题还没有解决,先贴出第4个实验:例6.7 8*8点阵LED显示控制设计
思考与实践
&#61692;1、本例程与数码管显示程序有非常多的类似地方,请读者自己分析程序的功能。

&#61692;2、请给出程序中的时间分配情况,如何调整箭头移动的速度的快慢,而又不影响正常的显示?
   答:将马老师源代码倒数第7行“if (++time_counter >=4) ”改成“if (++time_counter >=10) ”
       就可以放慢移动速度了。

&#61692;3、如果将display()函数中的语句“PORTC = ~(1<<i);”改为“PORTC = ~(1<<(7-i));”,显示有何变化?
   答:箭头方向由向上变为向下

&#61692;4、设计一个水平移动的8*8点阵广告,能够显示“今天YOU ARE OK?”

     我偷点懒,实现了水平向右显示“今天”。码值表如下

源代码如下:
/*********************************************
file name           : jintian.c
Chip type           : ATmega16
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
此程序的作用是在8X8点阵上实现“今 天”的右移
*********************************************/

#include <mega16.h>
#include <delay.h>


flash char char_16[16]={0xEF,0xEF,0xD7,0xA1,0x16,0xD7,0xEF,0xF7,0xff,0xee,0xad,0xab,0x87,0xab,0xad,0xee};//其中0xff为一空格

void display(char col)
{
        char i;
        for (i=0;i<=7;i++)
        {
                if (col <= 15)
                        PORTC = char_16[col];
                else
                        PORTC = 0XFF;
                PORTA = 1<<i;  //在这里可以修改移动方向
                delay_ms(2);
                PORTA = 0x00;
                if (++col >= 20 ) col = 0;                
        }
}

void main(void)
{
        char time_counter,i = 0;
        PORTC=0xFF;
        DDRC=0xFF;
        PORTA=0x00;
        DDRA=0xFF;

        while (1)
        {
                display(i);
                delay_ms(9);
                if (++time_counter >= 20)  //在这里可以修改移动速度
                {
                        time_counter = 0;
                        if(++i >= 20) i=0;
                }  
        };
}

出0入0汤圆

 楼主| 发表于 2007-10-8 18:05:38 | 显示全部楼层
第5个实验:P6-26 例6.8 16*2标准LCD字符显示器应用设计
先指出马老师讲义上的一个打印错误:P6-26关于void lcd_gotoxy(unsigned char x, unsigned char y)的说明,
“该函数将显示位置定位于第x行的第y列的位置处。”应该更正为“该函数将显示位置定位于第y行的第x列的位置处。”

我在实验板上完成了讲义中的两个实验,现贴出我自己写的一个小程序,
这个程序的功能是在1602上显示“User define arrow:箭头符号”,已经在板子上运行成功。
其中的一个函数void define_char(byte flash *pc,byte char_code)我没有弄懂,请求过来人注解。谢谢!

/*
file name           : arrow.c
Chip type           : ATmega16
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*/     
  
/* 包含头文件 */
#include <mega16.h>  
#include <lcd.h>
/* LCD 连接 PORTC */
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm

typedef unsigned char byte;
/* 自定义字符的点阵数据,一个指向右上角的箭头 */
flash byte char0[8]={
0b0000000,
0b0001111,
0b0000011,
0b0000101,
0b0001001,
0b0010000,
0b0100000,
0b1000000};

/* 定义自定义字符 ,以下六行请求过来人注释,谢谢!*/
void define_char(byte flash *pc,byte char_code)
{
   byte i,a;
   a=(char_code<<3) | 0x40;
   for (i=0; i<8; i++) lcd_write_byte(a++,*pc++);
}

void main(void)
{
   /* 初始化2 行16列LCD */
   lcd_init(16);
   /* 定义自定义字符0 */
   define_char(char0,0);
   /* 写显存 */
   lcd_gotoxy(0,0);
   lcd_putsf("User define arrow:");
   /* 显示自定义字符0 */
   lcd_putchar(0);
   while (1);
}

出0入0汤圆

发表于 2007-10-8 22:43:30 | 显示全部楼层
你这样做收获不会很大,要仔细分析程序,真正了解程序的思路和方法。做到看程序后就能知道85%(甚至是100%)的运行情况,然后下载验证。

例如,你回答的:

2、请给出程序中的时间分配情况,如何调整箭头移动的速度的快慢,而又不影响正常的显示?
   答:将马老师源代码倒数第7行“if (++time_counter >=4) ”改成“if (++time_counter >=10) ”
       就可以放慢移动速度了。  

3、如果将display()函数中的语句“PORTC = ~(1<<i);”改为“PORTC = ~(1<<(7-i));”,显示有何变化?
   答:箭头方向由向上变为向下

是读程序就分析出来的,还是看到现象后得出的?时间分配情况应该仔细分析:LED扫描的时间;字符移动的时间;是否有相互的影响;时间应该精确到ms。

==================================================================================================================
下面对你7楼的“今天”右移程序做个点评,请参考。

1。比箭头的上下移动有进步,知道将PA和PC换用,比我大部分的学生做的好。(得75分)
   我的学生他们通常直接使用箭头程序,然后把板顺时针转90度,说实现了右移,偷懒的做法(只能得30分)。
   当然在实际产品的设计中,应该使用把LED转90度的硬件设计,使软件设计方便。
   但在这里就是偷懒了,因为我的硬件已经设计完成了,如果是一个大型广告牌,你总不能把它转90度安装吧。这个练习主要是训练软件设计的,简单照搬程序不提倡。

2。为什么你只能得75分呢?不知道你是否观察到你的LED有些列亮,有些列暗,例如某列上有多个LED亮的话,该行的平均亮度就比较暗。原因再于你没有充分考虑和发挥I/O的驱动能力。
   在你的程序中,PA口输出1,负责1列,该列中如有8个LED亮,PC输出全0(所以你的码值表PC是取反的)。8个LED全亮,需要8*5=40ma电流,而AVR的I/O输出“1”时,只能输出20ma电流,所以LED就不够亮。而AVR的I/O口输出“0”时,最大的灌电流可以达到40ma。所以最好还是一行一行的扫描,但如何巧妙的设计程序就看你了。当然就比箭头的上下移动要复杂了。
   作为程序的设计练习,建议你再考虑考虑,争取得到100分。

3。这个例子也说明硬件设计的重要性。如果硬件设计的好,软件的编写可以方便很多,这也是嵌入式系统设计的特点,所以不要忽视硬件的设计和技巧,这也是一般人不重视的。

4。已经有人将我的书(讲义)是入门的,我也认为是入门的,但象我这样的入门深度,恐怕是其它大多数的入门书所不能及的。所以请你仔细、认真的、踏踏实实的入门。

5。到目前还没有几个(包括我上课的学生)能真正的深入思考和仔细和全面的回答我讲义中的问题,例子也是模仿、照搬的多,希望你不是这样的。

出0入0汤圆

 楼主| 发表于 2007-10-9 09:22:54 | 显示全部楼层
谢谢马老师指导!

出0入0汤圆

 楼主| 发表于 2007-10-9 19:05:41 | 显示全部楼层
第4个实验:例6.7 8*8点阵LED显示控制设计 的补充

个人水平太烂,今天花了一天的时间,初步解决了马老师提出的每一列的亮度的问题。
虽然运行实现了,但感觉有些别扭。

以下是源代码:

/*********************************************
writer:         
file name           : jintian_liangdu.c
Chip type           : ATmega16
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
功能:实现“今天”右移。   
此程序解决了jintian.c中LED有些列亮,有些列暗的问题,
线路连接如下:
     JE1 - 8  PA0 (M16)
     JE1 - 7  PA1 (M16)
     JE1 - 6  PA2 (M16)
     JE1 - 5  PA3 (M16)
     JE1 - 4  PA4 (M16)
     JE1 - 3  PA5 (M16)
     JE1 - 2  PA6 (M16)
     JE1 - 1  PA7 (M16)

     JE2 - 1  PC0 (M16)
     JE2 - 2  PC1 (M16)
     JE2 - 3  PC2 (M16)
     JE2 - 4  PC3 (M16)
     JE2 - 5  PC4 (M16)
     JE2 - 6  PC5 (M16)
     JE2 - 7  PC6 (M16)
     JE2 - 8  PC7 (M16)
*********************************************/

#include <mega16.h>
#include <delay.h>
/*    码值表              0x10,0x18,0x34,0x4b,0xbc,0x08,0x08,0x10,       //今
                          0x00,0x3e,0x08,0x7f,0x08,0x14,0x22,0x41        //天*/                             
flash int rowcode[]= {0x0010,0x3e18,0x0834,0x7f4b,0x08bc,0x1408,0x2208,0x4110};

void display(char col)
{
  char i;      

        for (i=0;i<=7;i++)
        {
            PORTA = rowcode>>col;
            PORTC = ~(1<<i);                  //行扫描
            delay_ms(2);
            PORTC = 0xFF;
        }   
        PORTC = 0xFF;   

}


void main(void)
{
        char time_counter,i = 0;
        PORTA=0x00;
        DDRA=0xFF;
        PORTC=0x00;
        DDRC=0xff;

        while (1)
        {
                display(i);
                delay_ms(9);
                if (++time_counter >= 4)
                {
                        time_counter = 0;
                        if(++i >= 16) i=0;
                }
        };
}

出0入0汤圆

发表于 2007-10-9 22:42:20 | 显示全部楼层
还是不符合要求,如果是10个字的话,你的数据结构根本不能使用。

你要设计使用一个好的数据结构,使编写的程序为通用的程序,可以满足1-N个字的右移(只要改动文字的定义,和说明N是几就可以),再考虑考虑。

出0入0汤圆

 楼主| 发表于 2007-10-12 20:13:16 | 显示全部楼层
这两天老师和我商量,要开始做一个项目。实现烤烟的自动控制,这个项目我在暑假已经用51实现了,但还不够完善。
现在打算用MEGA64或MEGA128做,因此“10.1长假结束,决定用一个月做马潮老师讲义上的主要实验。”这个帖子可能耽误,
不能及时更新。深表歉意。

这个项目很小,只需要用到AVR的I/O口和定时器,实现温度湿度采集,数码显示,语音提示,
2个220V 和1个380V的机器开关控制。


知道这样不坚持系统学习很浮躁。。。但老师交代的事,迫不得以。以后还有很多地方需要向马老师请教。

谢谢!

出0入0汤圆

 楼主| 发表于 2007-10-12 21:18:05 | 显示全部楼层
马老师能不能给个CodeVisionAVR的序列号?试用版的好象有很多函数用不了,比如说温度函数。谢谢!
我的邮箱 wujunyongjior618@sina.com

出0入0汤圆

发表于 2007-10-14 00:32:56 | 显示全部楼层
http://file.mcu123.com/

出0入0汤圆

发表于 2007-10-25 19:59:02 | 显示全部楼层
马潮老师讲义在哪能下载,谢谢!

出0入0汤圆

发表于 2007-10-25 20:22:22 | 显示全部楼层
转到“马潮老师专栏(AVR)”中,就在你的头上叫你呢。

小声讲一下,可能你学AVR很吃力,因为这个网站的东西和内容你都不会自己仔细了解的话,AVR的手册你是不会很好的看了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-22 22:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表