实验一 熟悉C程序运行环境
一、实验目的
1. 熟悉C语言Visual C++6.0调试环境。
2. 掌握C程序的编辑、调试及运行。
二、实验内容
项目1. 调试并运行下面程序,并写出运行结果:
#include <stdio.h>
int main(){
printf(“Good morning!\n);
printf(“Hello,world!\n”);
return 0;
}
运行结果(注意,按照屏幕输出格式写):
项目2. 调试并运行下面程序,并写出运行结果:
#include <stdio.h>
int main(){
int a , b , sum; /*定义变量*/
a=23; b=56; /*为变量赋值*/
sum=a+b; /*计算两个变量的和*/
printf(“sum is %d\n”,sum); /*输出计算结果*/
return 0;
}
运行结果:
项目3. 调试并运行下面程序,并写出运行结果:
#include <stdio.h>
int max(int,int);
int main(){
int a , b , c; /*定义变量*/
a=23; b=56; /*为变量赋值*/
c=max(a,b); /*调用max函数,将得到的值赋给c*/
printf(“max is %d\n”,c); /*输出c的值*/
return 0;
}
int max(int x,int y) { /*定义max函数,函数值为整型*/
int z; /*定义变量*/
if(x>y) z=x;
else z=y;
return(z); /*将z的值返回*/
}
运行结果:
三、提高部分
1.试想,如果求10个数中的最大者,则程序该如何编写。
程序代码
运行结果:
实验二 数据及其运算
一、实验目的
1. 掌握C数据类型的概念、熟悉整型、字符型和实型基本类型的常量的用法;学会三种基本类型变量的定义、赋值和使用方法。
2. 掌握算术表达式、关系表达式及逻辑表达式的特点及用法。
3. 熟悉运算符的优先级和结合性的概念。
4. 学习简单程序的编写方法。
二、实验内容
项目1. 编辑运行下面程序,并分析运行结果。
#include<stdio.h>
int main(){
int m,a,b,c,d,e; /*定义整型变量*/
printf(“please input a data:m=”);
scanf(“%d”,&m); /*从键盘输入一个整数*/
a=m+1;
b=m-2;
c=m*3;
d=m/4;
e=m%5;
printf(“a=m+1;a=%d\n”,a);
printf(“b=m-2;b=%d\n”,b);
printf(“c=m*3;c=%d\n”,c);
printf(“d=m/4;d=%d\n”,d);
printf(“e=m%5;e=%d\n”,e);
return 0;
}
运行结果:
项目2. 编辑运行下面程序,并分析运行结果。
#include<stdio.h>
int main(){
float m,n,s;
printf(“m=”);
scanf(“%f”,&m); /*输入矩形的边长*/
printf(“n=”);
scanf(“%f”,&n); /*输入矩形的边长*/
s=m*n; /*计算矩形的面积*/
printf(s=%f\n”,s); /*输出矩形的面积*/
return 0;
}
(1)输入24和5,运行结果:
(2)输入-24和5,运行结果:
分析结果是否正确?
(3)对上面程序进行修改,当输入一个非法的边长(负数或零),会给出提示而不计算矩形的面积。
输入-24和5,运行结果:
项目3. 先阅读程序,并写出结果,再运行程序并分析结果。
#include<stdio.h>
int main(){
int i,j,m,n,p,q,x,y;
i=8;j=10;p=0;q=0;x=1;y=1;
m=++i;
n=j++;
p+=i++;
q-=--j;
x+=m+10;
y=p==q;
printf(“i=%d,j=%d,m=%d,n=%d,p=%d,q=%d,x=%d,y=%d”,i,j,m,n,n,p,q,x,y);
return 0;
}
分析结果:
i=_____;j=_____;m=_____;n=_____;p=_____;q=_____;x=_____;y=_____
运行结果:
项目4.(选做)
根据矩形面积的计算方法,编写一个输入圆半径r,计算园周长L和圆面积S的程序。注意判断圆半径r是否大于零。(程序代码和运行结果可写在指导书背面)
实验三 程序控制结构(选择)
项目1.三角形成立条件判断及面积计算
【项目任务】输入三个整型数据,判断这三个整型数据能否围成三角形,如果能组成三角形,计算并输出它的面积,如果不能围成三角形输出“三条边不能围成三角形”。
【项目说明】
C语言实现选择结构筑要用if语句,按照判断所给定的条件是否满足,根据判定结果的真或假来决定执行在if语句中给出的两种操作之一。
【项目目的】
(1)正确使用关系表达式和逻辑表达式表达条件。
(2)学习分支语句if的使用方法。
(3)进一步熟悉VC集成环境的使用方法,学习VC环境提供的调试工具。
【项目要点】
(1)已知三边求三角形面积的公式:
P=(a+b+c)/2 S=
(2)已知三边能围成三角形的条件是:任意两边之和大于第三边。
(3)C语言中求平方根的函数是sqrt(double x),该函数在math.h头文件中。
(4)if语句中“表达式”必须用“(”和“)”括起来,它的值为逻辑值。除常见的关系表达式或逻辑表达式外,也允许是其他类型的数据,如整型、实型、字符型等。
(5)else子句(可选)是if语句的一部分,必须与if配对使用,不能单独使用。
程序代码:
运行结果:
项目2. 百分制成绩转换为成绩等级
【项目任务】
输入一个百分制成绩,输出对应的等级。
【项目目的】
(1)正确使用关系表达式和逻辑表达式表达条件。
(2)学习多switch分支选择语句的使用方法。
【项目要点】
解决本项目的关键是如何将输入的百分制成绩与case常量联系起来,不难想到将百分制成绩(用score表示)除以10之后再取整,一定得到0到10之间的数。9、10对应’a’,8对应‘b‘,……,5、4、3、2、1、0对应’e’既不及格。
程序代码:
运行结果:
项目3.选做
。
(程序代码和运行结果可写在指导书背面)
#include<stdio.h>
int main()
{
float x,y;
printf("请输入x的值");
scanf("%f",&x);
if (x>0) y=2*x+1;
else if (x=0) y=0;
else y=-x-1;
printf("y的值为:%f\n",y);
}
实验四 程序控制结构(循环)
项目1:使用循环结构实现重复处理
【项目说明】
从键盘输入一个班的成绩,把百分制转换成等级制。将百分制成绩(用score表示)除以10之后再取整,一定得到0到10之间的数。9、10对应’a’,8对应‘b‘,……,5、4、3、2、1、0对应’e’既不及格。要求分别使用三种循环结构实现。该项目中,假设班级人数不固定,规定输入若干0至100的成绩,如果成绩不在此范围,则表示结束。该项目中,同时要使用switch语句实现多分支选择结构。
【项目目的】
(1)掌握用while语句和do…while语句实现循环的方法。
(2)掌握用for语句实现循环的方法。
(3)掌握三种语句的特点和应用技巧。
(4)掌握用break语句和continue语句改变循环状态的方法 。
【项目内容】
1、用while语句实现的程序代码:
2、用do…while和break语句实现的程序代码:
3、用do…while和continue语句实现的程序代码:
4、用for语句实现的程序代码:
项目2.(选做)
求(即求)(程序代码和运行结果可写在指导书背面)
实验五 数组
项目1.冒泡排序法
【项目说明】
输入10个数,用“冒泡法”对10个数排序(由小到大)。冒泡法的基本思想:通过相邻两个数之间的比较和交换,使(数值)较小的数逐渐从底部移向顶部,较大的数逐渐从顶部移向底部。就像水底的气泡一样逐渐向上冒,故而得名。
【项目目的】
(1)掌握冒泡排序算法的编程。
(2)掌握与数组有关的算法。
程序代码:
运行结果:
项目2.字符统计
【项目说明】
有一篇文章,共有3行文字,每行80个字符。要求分别统计出其中英文字母和数字的个数。
【项目目的】
(1)掌握键盘输入字符串方法。
(2)掌握二维数组的处理方法。
【技术要点】
(1)3行文字可定义一个二维字符数组来表示。
(2)使用gets( ) 函数对字符串进行输入。
程序代码:
运行结果:
项目3.(选做)
在二维数组中,若某一位置上的元素在该行中最大,而在该列中最小,则该元素即为该二维数组的一个鞍点。要求从键盘上输入一个二维数组,当鞍点存在时,把鞍点找出来。
(程序代码和运行结果可写在指导书背面)
实验六 函数
项目1:使用函数实现对二维数组转置。
【项目说明】
写一个函数,使给定的3*3的二维整型数组转置,即行列互换。要求输出转换之前和转换之后的结果。
【项目目的】
(1)掌握函数的定义和调用。
(2)掌握二维数组名作为函数的参数的使用技巧。
【技术要点】
(1)使用二重循环对二维数组进行输入,处理和输出;
(2)二维数组名作为函数的参数,定义函数需要给出第二维的大小。
程序代码:
运行结果:
项目2:使用函数实现成绩处理
【项目说明】
输入3个学生4门课的成绩,分别用函数实现以下功能:(1)计算每个学生的平均分。(2)计算每门课的平均分。(3)找出12个分数中最高分数所对应的学生和课程。
【项目目的】
(1)掌握函数的定义和调用。
(2)掌握全局变量的使用。
【技术要点】
学生成绩可定义成全局的二维数组,这样自定义函数可以直接使用,而不需要进行参数的传递。
程序代码:
运行结果:
项目3.(选做)
求(即求)(阶乘要求使用递归函数来实现,程序代码和运行结果可写在指导书背面)
实验七 指针
项目1.使用指针参数交换两个变量值
【项目说明】
用函数实现两个变量值的交换,使其在主调函数和被调函数中的值一致,并且返回这两个变量的和以及乘积。要求用指针变量作为函数参数。
【项目目的】
(1)熟悉如何定义指针变量,掌握将指针变量作为函数参数的方法。
(2)掌握通过指针参数由被调函数向主调函数传递多个值的方法。
【技术要点】
由于变量的值始终存放在内存单元中,因此,要交换两个变量的值,只需交换这两个
变量对应的存储单元的值即可,这就需要知道两个变量的地址。也就是说,需要保证主调
函数与被调函数中所要交换的两个数的内存单元是同一内存单元,即传递的参数是内存单
元的地址,而不是内存单元中的值。
程序代码:
运行结果:
项目2. 数组的排序和的插入
【项目目的】
(1)熟悉如何定义指针变量,掌握将指针变量指向一维数组元素的方法。
(2)掌握如何对数组进行排序。
(3)掌握如何在一个有序的数列中查找合适的位置。
(4)掌握如何将一个数插入到一个有序数列中。
【技术要点】
(1)排序可采用冒泡法或者选择法。
(2)有序数组中插入一个数的关键是找到该数据插入的位置,然后将插入位置及其后的所有元素均后移一位,在空出的位置放入待插入的数据。例如,在 13、27、38、49、65、76、97 这列有序数据中插入 53 这个数,成为新的有序数列 13、27、38、49、53、65、76、97。
(4)定义数组时多开辟一个存储单元,用于存放待插入的数据。
程序代码:
运行结果:
项目3.(选做) (程序代码和运行结果可写在指导书背面)
编写函数 int find(int *p,int n,int x),在指针 p 所指的数组中查找整型数 x,如果 x 在数组中,则该函数返回 1,否则返回 0。n 为数组的大小。编写主函数测试之。
第二篇:AVR单片机C语言程序设计实验指导书
实验一 发光二极管的移动控制
一、实验目的
1.熟悉并行接口的设置与应用;
2.进一步熟悉编译软件和下载软件的使用;
3.熟悉C语言中移位、延时、数组等指令的应用;
4.增强学习单片机的兴趣。
二、实验内容
1.参考课本P128“发光二极管的移动控制”实验程序,实现发光二极管循环点亮的按键控制。
2.设计一个完整程序(另建一个文档),实现8个led灯的自动顺序(加法)点亮和逆序(减法)点亮。见参考程序,并在程序中添加必要的解释文字。
三、实验步骤
1.以班级和姓名为文件夹名称在D盘根目录下新建一个子目录文件夹,用来保存每次实验的项目和程序。(注意:每次实验的位置固定,即下次实验的计算机还是上次的计算机。)
2.再在这个子目录下以实验题目为名新建一个文件夹。打开ICCAVR开发编程软件,新建一个工程文件项目,参照程序清单或根据实验要求自己重新修改设置并输入程序。
3.保存程序,并将程序源文件添加到项目里。见下图1。
图1
4.设置项目属性,选择目标芯片等,见下图2,3。
图2 图3
5.编译程序。将所输入的程序进行编译(菜单Project→ Make命令),或者在工具栏单击按钮),若编译时下方出现错误提示,说明程序有语法错误,此时必须根据编译器所列出的错误消息,逐条查改,重新编译,直到错误消除并生成*.hex文件。
6.功能仿真。利用proteus或AVR studio的仿真功能对程序进行功能性仿真,验证程序功能是否正确。
7.打开下载软件(progisp或AVR Studio里的JTAG ICE),将刚刚生成的相应*.hex文件写入单片机(在此之前,须将单片机实验板按要求与PC机连接正确,并接通电源)。
8.验证硬件实现的结果是否与功能要求一致。
四、参考程序(实现8个led灯的自动顺序(加法)和逆序(减法)点亮的部分程序)
/***********************
系统外接8M晶振
************************/
unsigned char i;
while (1) {
for (i = 0; i < 8; i ++) {
PORTB = ~(1 << i);
delay_ms(200);
}
for (i = 8; i > 0; i --) {
PORTB = ~(1 << i-1);
delay_ms(200);
}
}
实验二 0~99数字的加减控制
一、实验目的
1.熟悉并行接口的设置与应用;
2. 进一步熟悉编译软件和下载软件的使用;
3.熟悉十进制数各个位在数码管上显示的编程方法;
二、实验内容
1.参照课本P131“0~99数字的加减控制”的程序,实现按键对数字的加减控制功能(因实验板上数码管与PC口的连接方式和书本中的连接不一致,须修改源程序,具体见实验电路分析部分)。
2.假如需要控制0~999数字的加减控制,请重新设计一个程序实现该功能。
三、实验电路
本实验的电路连接如下图所示1。注意:本图中高位数码管连接低位PC口,低位数码管连接高位PC口,即图中第1位(最左边)数码管连接PC0,第2位数码管连接PC1,…,第8位(最右边)数码管。与课本的实验电路连接方式不一致,故在程序设计中需要修改数码管的位选端。
图1 键控计数电路
四、实验步骤
参照实验一的实验步骤过程。
1.参照课本P131,通过ICCAVR编译后生成*.HEX文件,并利用proteus ISIS仿真程序实现的功能。
2.在不修改数码管位选端的情况下,观察程序执行结果。
3.分别修改数码管的个位和十位位选端,使数码管上显示的结果正常。
4.如要使数字的显示从数码管的最低位开始显示,重新设计数码管的个位和十位位选端编码。
5.若要控制0~999数字的加减控制,设计数码管的BCD转换。
五、部分参考程序
1.实验板上各个数码管的位选端数组为:
ACT[8] ={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f} //数码管从高位到低位显示//的排列编码
2.数码管BCD转换:
PORTA=SEG7[counter%10]; //显示counter变量的个位
PORTC=ACT[0]; //选通个位数码管
delay_ms(1);
PORTA=SEG7[counter/10%10]; //显示counter变量的十位
PORTC=ACT[1]; //选通十位数码管
delay_ms(1);
PORTA=SEG7[counter/100]; //显示counter变量的百位
PORTC=ACT[2]; //选通百位数码管
delay_ms(1);
实验三 脉宽调制(PWM)实验
一、实验目的
1. 进一步了解脉宽调制的意义,熟悉脉宽调制的原理;
2. 掌握脉宽调制的设置与应用;
3. 能解读程序。
二、实验内容
1.参照课本P234“PWM测试实验”的程序,实现按键S1、S2对PWM的输出控制。
(1)编译通过后,进行软件仿真。在Proteus ISIS里利用LCD1602观察显示内容是否正确,并用虚拟示波器(OSCILLOSCOPE)观察OC2引脚(PD7)输出的PWM信号是否正常。见下图。
注意:开始仿真后,必须按下S1才有PWM波输出。
(2)用数字万用表检测OC2脚(PD7),观测输出电压是否与LCD指示的相符,并填入下表。
2.修改源程序(P234~P236),使输出脉宽是自动变化的。部分参考程序如下:
while (1) {
unsigned char i;
i = 255;
while (i) {
OCR2 = i;
Delay_nms(50);
i --;
}
i = 1;
while (i) {
OCR2 = i;
Delay_nms(50);
i ++;
}
}
三、附LCD1602驱动参考程序
(注:本驱动是在课本P182~185基础上进行修改的,目的是删除驱动程序中的检测LCD忙信号函数及与其相关语句,使仿真和显示正常。)
/*******LCD1602液晶驱动程序***************/
#include <iom16v.h>
#include <macros.h>
#define xtal 8
#define PB0 0
#define PB1 1
#define PB2 2
//----------------------------
#define uchar unsigned char
#define uint unsigned int
#define SET_BIT(x,y) (x|=(1<<y))
#define CLR_BIT(x,y) (x&=~(1<<y))
#define GET_BIT(x,y) (x&=(1<<y))
//-------端口电平的宏定义------------
#define LCM_RS_1 SET_BIT(PORTB,PB0)
#define LCM_RS_0 CLR_BIT(PORTB,PB0)
#define LCM_RW_1 SET_BIT(PORTB,PB1)
#define LCM_RW_0 CLR_BIT(PORTB,PB1)
#define LCM_EN_1 SET_BIT(PORTB,PB2)
#define LCM_EN_0 CLR_BIT(PORTB,PB2)
//------------------------------
#define DataPort PORTA
#define Busy 0x80
//**********函数声明********************
void Delay_1ms(void);
void Delay_nms(uint n);
void LcdWriteData(uchar W);
void LcdWriteCommand(uchar CMD);
void InitLcd(void);
void DisplayLine2(uchar dd);
void DisplayOneChar(uchar x,uchar y,uchar Wdata);
void ePutstr(uchar x,uchar y,uchar const *ptr);
/***********显示指定坐标的一串字符子函数************/
void ePutstr(uchar x,uchar y,uchar const *ptr)
{
uchar i,l=0;
while(ptr[l]>31){l++;}
for(i=0;i<l;i++){
DisplayOneChar(x++,y,ptr[i]);
if(x==16){
x=0;y^=1;
}
}
}
//**********演示第二行移动字符串子函数************
void DisplayLine2(uchar dd)
{
uchar i;
for(i=0;i<16;i++){
DisplayOneChar(i,1,dd++);
dd&=0x7f;
if(dd<32)dd=32;
}
}
//***********显示光标定位子函数******************
void LocateXY(char posx,char posy)
{
uchar temp=0;
temp&=0x7f;
temp=posx&0x0f;
posy&=0x01;
if(posy)temp|=0x40;
temp|=0x80;
LcdWriteCommand(temp);
}
//**********显示光标定位的一个字符子函数***********
void DisplayOneChar(uchar x,uchar y,uchar Wdata)
{
LocateXY(x,y);
LcdWriteData(Wdata);
}
//***********LCD初始化子函数******************
void InitLcd(void)
{
LcdWriteCommand(0x38);//显示模式设置(固定),8位数据接口
Delay_nms(5);
LcdWriteCommand(0x01);//清屏
Delay_nms(5);
LcdWriteCommand(0x0c);//开显示,不显示光标
Delay_nms(5);
}
//************写命令到LCM子函数************
void LcdWriteCommand(uchar CMD)
{
LCM_RS_0;LCM_RW_0;
DataPort=CMD;
LCM_EN_1;Delay_nms(1);LCM_EN_0;
}
//************写数据到LCM子函数*************
void LcdWriteData(uchar dataW)
{
LCM_RS_1;LCM_RW_0;
DataPort=dataW;
LCM_EN_1;Delay_nms(1);LCM_EN_0;
}
//***********1ms延时子函数*******************
void Delay_1ms(void)
{ uint i;
for(i=1;i<(uint)(xtal*143-2);i++)
;
}
//=============n*1ms延时子函数================
void Delay_nms(uint n)
{
uint i=0;
while(i<n)
{Delay_1ms();
i++;
}
}
实验四 0~5V数字式直流电压表
一、实验目的
1. 掌握A/D转换程序的设计;
2. 掌握数据采集与显示的应用;
3.掌握数据处理的方法;
二、实验内容
1. 参照课本P383页“0~5V数字式直流电压表实验”程序,并编译、仿真,见下图所示。
注意:由于用proteus ISIS仿真时,数码管模型显示的闪烁现象和缓存现象,需要对其进行短延时和清屏,否则,显示将出现乱码现象。可在main()主函数里加入两条语句:
Delay(1);
PORTA=0;
(1)修改错误。
比较程序第25行“ADMUX=0XC7”以及程序第71行“x=(5000*(long)i)/1023”所指参考电压不一致,导致输入模拟电压值与数码管显示电压值不一致,有哪几种修改方案。
如把ADMUX=0XC7改为0X07。
(2)调节电位器(POT-LOG),观察数码管显示的电压值与虚拟直流电压表显示的电压是否一致。
2.将编译通过后的程序烧写到单片机里,调节AD电位器,观看开发板上数码管的显示情况。
注意数码管的位选端排列顺序,实验板与课本电路图中数码管排序不同,故需要调整位选端。
3.如果想观察ADC转换后的数字结果,则需将数码管显示改为:
PORTA=SEG7[adc_val%10];
………
依次类推。
三、拓展实验
把数码管显示改为LCD1602液晶显示。(可参考P240“0~5V数字电压调整器”lcd部分程序内容)
注意:因使用PA7为输入端口,而PA口为原电路中LCD1602的数据端口,故把数据端口改为PC口,注意要把lcd1602液晶的驱动程序“lcd1602_8bit.c”中的语句“#define DataPort PORTA”改为“#define DataPort PORTC”。Proteus ISIS仿真图如下图。
四、附使用LCD1602显示ADC参考程序
#include <iom16v.h>
#include "lcd1602_8bit.c"
uchar const title[]={"0-5v D_voltager"};
#define uchar unsigned char
#define uint unsigned int
uint adc_val,dis_val;
uchar i,cnt;
/************************************************/
void port_init(void)
{
PORTA = 0x7F;
DDRA = 0x7F;
PORTB = 0xFF;
DDRB = 0xFF;
PORTC = 0xFF;
DDRC = 0xFF;
PORTD = 0xFF;
DDRD = 0xFF;
}
/************************************************/
void adc_init(void) {
ADCSRA = 0xE3;
ADMUX = 0x47; }
//***************************
void timer0_init(void) {
TCNT0 = 0x83;
TCCR0 = 0x03;
TIMSK = 0x01;
}
/*********************************************/
void init_devices(void)
{
port_init();
timer0_init();
adc_init();
SREG =0x80;
}
//***************************
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
TCNT0 = 0x83;
cnt++;
}
//=========================
uint ADC_Convert(void)
{uint temp1,temp2;
adc_init();
temp1=(uint)ADCL;
temp2=(uint)ADCH;
temp2=(temp2<<8)+temp1;
return(temp2);
}
/**************************/
uint conv(uint i)
{
long x;
uint y;
x=(5000*(long)i)/1023;
y=(uint)x;
return y;
}
void delay(uint k)
{
uint i,j;
for(i=0;i<k;i++)
{
for(j=0;j<1141;j++);
}
}
/***********************/
void main(void)
{
init_devices();
Delay_nms(400);
DDRA=0X7F;PORTA=0X7F;
DDRC=0XFF;PORTC=0X00;
DDRB=0XFF;PORTB=0X00;
InitLcd();
ePutstr(1,0,title);
DisplayOneChar(0,1,'A');
DisplayOneChar(1,1,'D');
DisplayOneChar(2,1,'C');
DisplayOneChar(3,1,'7');
DisplayOneChar(4,1,':');
DisplayOneChar(11,1,'.');
DisplayOneChar(15,1,'V');
while(1)
{
if(cnt>100)
{
adc_val=ADC_Convert();
dis_val=conv(adc_val);
cnt=0;
}
delay(10);
DisplayOneChar(5,1,(adc_val/1000)+0x30);
DisplayOneChar(6,1,(adc_val/100)%10+0x30);
DisplayOneChar(7,1,(adc_val/10)%10+0x30);
DisplayOneChar(8,1,(adc_val%10)+0x30);
DisplayOneChar(10,1,(dis_val/1000)+0x30);
DisplayOneChar(12,1,(dis_val/100)%10+0x30);
DisplayOneChar(13,1,(dis_val/10)%10+0x30);
DisplayOneChar(14,1,(dis_val%10)+0x30);
}
}