10.1长假结束,决定用一个月做马潮老师讲义上的主要实验。
第一个实验:设计一个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函数。这是为什么?呵呵。 第二个实验:讲义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={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;
}
};
} 另外建议你把我的例程后面的问题与思考仔细想想,然后把答案贴上来,大家讨论。 给新人一些建议.
在大家编程之前,先去看看华为公司的软件编程规范,网上很容易看到的.
最起码我看到上面的软件例子的时候就感觉蛮便扭的.
简单看了两眼,不像出自一个单片机软件高人的手笔.变量命名规则有待改进.char之类的和编译器有关的东西没有用宏,等等.
还有好几处不合适的地方,我就不指出了.
虽然大家会认为这只是个小实验,随便点无所谓.
但一个在软件上有些资历的人编程会有一些风格的,其实只要有一点点地和自己风格不一样的地方,都会让自己非常的不舒服.一定会改掉的,所以我们基本能从简单的一小段代码中看出一个人对程序的理解度,和写程序的实力,更能看出一个人的阅历. 一个资深的软件设计师形成的5个阶段:
1: 入门阶段: 读大量的程序,能够自己修改和拼凑出一个能实现功能的程序. 可以完成简单的软件工作.
2: 合格阶段: 熟知各种知名的程序风格,形成自己的风格,并能够独立完成一个超过1W行代码的项目,基本无错误.
3: 优秀阶段: 熟读各种系统内核源码,能够正确评判代码的质量,效率,优缺点. 十分考究冗余性,扩展性,纠错性等,能够在大型软件项目中担任核心成员.
4: 核心阶段: 能够自己编写出优秀操作系统之类内核源码,能够带领团队完成大型软件工程.
5: 专家阶段: 可以有创立一种更加优秀的软件思想的专家.能够权威并且正确无误的批判所有软件质量的专家. 同意3楼,养成良好的习惯有时候比掌握一门技术更重要,尤其对初学者 感谢以上两位的指教!
做第三个实验P6-17例6.5 六位LED数码管动态扫描控制显示设计(一)出现了点问题。。。用马老师的代码昨天晚上能够从时间初始值23:58:55正常运行,今天再做的时候6个数码管显示全为“0”,2个小数点位还在每隔1秒闪烁。怀疑数码管坏了,重做第2个实验,结果正常。不知道问题在哪儿。
http://cache.amobbs.com/bbs_upload782111/files_8/ourdev_175744.JPG 第3个实验的问题还没有解决,先贴出第4个实验:例6.7 8*8点阵LED显示控制设计
思考与实践
1、本例程与数码管显示程序有非常多的类似地方,请读者自己分析程序的功能。
2、请给出程序中的时间分配情况,如何调整箭头移动的速度的快慢,而又不影响正常的显示?
答:将马老师源代码倒数第7行“if (++time_counter >=4) ”改成“if (++time_counter >=10) ”
就可以放慢移动速度了。
3、如果将display()函数中的语句“PORTC = ~(1<<i);”改为“PORTC = ~(1<<(7-i));”,显示有何变化?
答:箭头方向由向上变为向下
4、设计一个水平移动的8*8点阵广告,能够显示“今天YOU ARE OK?”
我偷点懒,实现了水平向右显示“今天”。码值表如下
http://cache.amobbs.com/bbs_upload782111/files_8/ourdev_175825.JPG
源代码如下:
/*********************************************
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={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;
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;
}
};
} 第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={
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);
} 你这样做收获不会很大,要仔细分析程序,真正了解程序的思路和方法。做到看程序后就能知道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。到目前还没有几个(包括我上课的学生)能真正的深入思考和仔细和全面的回答我讲义中的问题,例子也是模仿、照搬的多,希望你不是这样的。 谢谢马老师指导! 第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 - 8PA0 (M16)
JE1 - 7PA1 (M16)
JE1 - 6PA2 (M16)
JE1 - 5PA3 (M16)
JE1 - 4PA4 (M16)
JE1 - 3PA5 (M16)
JE1 - 2PA6 (M16)
JE1 - 1PA7 (M16)
JE2 - 1PC0 (M16)
JE2 - 2PC1 (M16)
JE2 - 3PC2 (M16)
JE2 - 4PC3 (M16)
JE2 - 5PC4 (M16)
JE2 - 6PC5 (M16)
JE2 - 7PC6 (M16)
JE2 - 8PC7 (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;
}
};
} 还是不符合要求,如果是10个字的话,你的数据结构根本不能使用。
你要设计使用一个好的数据结构,使编写的程序为通用的程序,可以满足1-N个字的右移(只要改动文字的定义,和说明N是几就可以),再考虑考虑。 这两天老师和我商量,要开始做一个项目。实现烤烟的自动控制,这个项目我在暑假已经用51实现了,但还不够完善。
现在打算用MEGA64或MEGA128做,因此“10.1长假结束,决定用一个月做马潮老师讲义上的主要实验。”这个帖子可能耽误,
不能及时更新。深表歉意。
这个项目很小,只需要用到AVR的I/O口和定时器,实现温度湿度采集,数码显示,语音提示,
2个220V 和1个380V的机器开关控制。
知道这样不坚持系统学习很浮躁。。。但老师交代的事,迫不得以。以后还有很多地方需要向马老师请教。
谢谢! 马老师能不能给个CodeVisionAVR的序列号?试用版的好象有很多函数用不了,比如说温度函数。谢谢!
我的邮箱 wujunyongjior618@sina.com http://file.mcu123.com/ 马潮老师讲义在哪能下载,谢谢! 转到“马潮老师专栏(AVR)”中,就在你的头上叫你呢。
小声讲一下,可能你学AVR很吃力,因为这个网站的东西和内容你都不会自己仔细了解的话,AVR的手册你是不会很好的看了。
页:
[1]