1. c語言實驗報告心得
c語言實驗心得:
1、只有頻繁用到或對運算速度要求很高的變數才放到data區內,如for循環中的計數值。
2、其他不頻繁調用到和對運算速度要求不高的變數都放到xdata區。
3、常量放到code區,如字型檔、修正系數。
4、邏輯標志變數可以定義到bdata中。
在51系列晶元中有16個位元組位定址區bdata,其中可以定義8*16=128個邏輯變數。這樣可以大大降低內存佔用空間。定義方法是: bdata bit LedState;但位類型不能用在數組和結構體中。
5、data區內最好放局部變數。
因為局部變數的空間是可以覆蓋的(某個函數的局部變數空間在退出該函數是就釋放,由別的函數的局部變數覆蓋),可以提高內存利用率。當然靜態局部變數除外,其內存使用方式與全局變數相同;
6、確保程序中沒有未調用的函數。
在Keil C里遇到未調用函數,編譯器就將其認為可能是中斷函數。函數里用的局部變數的空間是不釋放,也就是同全局變數一樣處理。這一點Keil做得很愚蠢,但也沒辦法。
7、如果想節省data空間就必須用large模式。
將未定義內存位置的變數全放到xdata區。當然最好對所有變數都要指定內存類型。
8、使用指針時,要指定指針指向的內存類型。
在C51中未定義指向內存類型的通用指針佔用3個位元組;而指定指向data區的指針只佔1個位元組;指定指向xdata區的指針佔2個位元組。如指針p是指向data區,則應定義為: char data *p;。還可指定指針本身的存放內存類型,如:char data * xdata p;。其含義是指針p指向data區變數,而其本身存放在xdata區。
以前沒搞過C51,大學時代跟單片機老師的時候也是搗鼓下匯編,現在重新搞單片機,因為手頭資料不多,找到一些C51的程序,發現裡面有這些關鍵字,不甚明了,沒辦法只好找了下,發現如下描述:
從數據存儲類型來說,8051系列有片內、片外程序存儲器,片內、片外數據存儲器,片內程序存儲器還分直接定址區和間接定址類型,分別對應code、data、xdata、idata以及根據51系列特點而設定的pdata類型,使用不同的存儲器,將使程序執行效率不同,在編寫C51程序時,最好指定變數的存儲類型,這樣將有利於提高程序執行效率(此問題將在後面專門講述)。與ANSI-C稍有不同,它只分SAMLL、COMPACT、LARGE模式,各種不同的模式對應不同的實際硬體系統,也將有不同的編譯結果。
在51系列中data,idata,xdata,pdata的區別
data:固定指前面0x00-0x7f的128個RAM,可以用acc直接讀寫的,速度最快,生成的代碼也最小。
idata:固定指前面0x00-0xff的256個RAM,其中前128和data的128完全相同,只是因為訪問的方式不同。idata是用類似C中的指針方式訪問的。匯編中的語句為:mox ACC,@Rx.(不重要的補充:c中idata做指針式的訪問效果很好)
xdata:外部擴展RAM,一般指外部0x0000-0xffff空間,用DPTR訪問。
pdata:外部擴展RAM的低256個位元組,地址出現在A0-A7的上時讀寫,用movx ACC,@Rx讀寫。這個比較特殊,而且C51好象有對此BUG,建議少用。但也有他的優點,具體用法屬於中級問題,這里不提。
三、有關單片機ALE引腳的問題
"單片機不訪問外部鎖存器時ALE端有正脈沖信號輸出,此頻率約為時鍾振盪頻率的1/6.每當訪問
外部數據存儲器是,在兩個機器周期中ALE只出現一次,即丟失一個ALE脈沖."這句話是不是有毛
病.我覺得按這種說法,應該丟失3個ALE脈沖才對,我一直想不通是怎麼回事,希望大蝦們幫幫我.
小弟感激涕零.
答:
其他所有指令每6個機器周期發出一個ALE,而MOVX指令佔用12個機器周期只發出一個ALE
四、如何將一個INT型數據轉換成2個CHAR型數據?
經keil優化後,char1=int1/256,char2=int1%256或char1=int1>>8,char2=int1&0x00ff效率是一樣的。
五、在KEIL C51上模擬完了,怎樣生成HEX文件去燒寫??
右鍵點項目中Target 1,選第二個,在OUTPUT中選中CREAT HEX
六、typedef 和 #define 有何不同??
typedef 和 #define 有何不同》》》 如
typedef unsigned char UCHAR ;
#define unsigned char UCHAR ;
typedef命名一個新的數據類型,但實際上這個新的數據類型是已經存在的,只不過是定義了
一個新的名字.
#define只是一個標號的定義.
你舉的例子兩者沒有區別,但是#define還可以這樣用
#define MAX 100
#define FUN(x) 100-(x)
#define LABEL
等等,這些情況下是不能用typedef定義的
七、請問如何設定KELC51的模擬工作頻(時鍾)
用右鍵點擊左邊的的target 1,然後在xtal一欄輸入
八、不同模塊怎樣共享sbit變數,extern不行?
把SBIT定義單獨放到一個.H中,每個模塊都包含這個.h文件
九、C51中對於Px.x的訪問必須自己定義嗎?
是的。
如sbit P17 = 0x97;即可定義對P1.7的訪問
十、SWITCH( )語句中表達式不可以是位變數對嗎?
可以用位變數:
#include
#include
void main()
{
bit flag;
flag=0;
switch(flag)
{
case '0':{printf("0\n");break;}
case '1':{printf("1\n");break;}
default:break;
}
}
bit 變數只有兩種狀態,if 語句足夠啦,!!!
十一、const常數聲明占不佔內存???
const 只是用來定義「常量」,所佔用空間與你的定義有關,如:
const code cstStr[] = {"abc"};
佔用代碼空間;而如:
const char data cstStr[] = {"abc"};
當然佔用內存空間。
另外,#define 之定義似乎不佔用空間。
十二、philips的單片機P89C51RD+的擴展RAM在C51中如何使用?
試一試將auxr.1清0,然後在c語言中直接聲明xdata類型的變數
十三、BUG of Keil C51
程序中用如下語句:
const unsigned char strArr[] = {"數學"};
結果發現strArr[] 內容為 {0xCA,0xD1,0xA7},真奇怪!
凡是有0xfd,則會通通不見了,所以只能手工輸入內碼了,例如 uchar strArr[]=
{0xCA,0xfd,0xd1,0xa7}(用Ultraedit會很方便)。
十四、Keil C51中如何實現代碼優化?
菜單Project下Option for target "Simulator"的C51.
看到Code optimization了嗎?
十五、請教c的!和 ~ 符號有甚區別??
!是邏輯取反,~是按位取反。
十六、c51編程,讀埠,還要不要先輸出1?
我怎麼看到有的要,有的不要,請高手給講講,到底咋回事?謝了
要輸出1的,除非你能保證之前已經是1,而中間沒有輸出過其他值。
十七、當定時器1(T1)用於產生波特率時,P3^5還是否可以用作正常的I/O口呢?
p3.5完全可以當普通的io使用
十八、C51中 INT 轉換為 2個CHAR?
各位高手:
C51中 INT 轉換為 CHAR 如何轉換諸如:
X = LOW(Z);
Y = HIGH(Z);
答:
x=(char)z;
y=(char)(z>>8);
十九、如果我想使2EH的第7位置1的話,用位操作可以嗎?
現在對位操作指令我一些不太明白請各位多多指教:
如 SETB 07H 表示的是20H.7置1,對嗎?(我在一本書上是這么看到的)
那麼如果我想使2EH的第7位置1的話,象我舉的這個例子怎麼表示呢?謝謝!
SETB 77H
setb (2eh-20h)*8+7
20h-2fh每位元組有8個可位操作(00h-7fh),其它RAM不可位直接操作
二十、char *addr=0xc000 和char xdata *addr=0xc000有何區別?
char *addr=0xc000;
char xdata *addr=0xc000;
除了在內存中佔用的位元組不同外,還有別的區別嗎?
char *addr=0xc000; 是通用定義,指針變數 addr 可指向任何內存空間的值;
char xdata *addr=0xc000; 指定該指針變數只能指向 xdata 中的值;
後一種定義中該指針變數(addr)將少佔用一個存儲位元組。
uchar xdata *addr=0xc000;指針指向外ram;
如果:data uchar xdata *addr=0xc000;指針指向外ram但指針本身存在於內ram(data)
中
以此類推可以idata uchar xdata *addr=0xc000;pdata uchar xdata *addr=0xc000;
data uchar idata *addr=0xa0;.........
二十一、while(p1_0)的執行時間?
假設,P1_0為單片機P1口的第一腳,請問,
while(P1_0)
{
P1_0=0;
}
while(!P1_0)
{
P1_0=1;
}
以上代碼,在KEIL C中,需要多長時間,執行完。能具體說明while(P1_0)的執行時間嗎?
模擬運行看看就知道了,
我模擬了試了一下,約14個周期
二十二、怎樣編寫C51的watchdog程序?
各位大蝦,我用KEIL C51 編寫了一個帶外部開門狗的程序,可程序無法運行起來,經過查
找,發現程序在經過C51編譯後,在MAIN()函數的前部增加了一端初始化程序,等到進入
主程序設置開門狗時,開門狗已經時間到,將我的程序復位了,請問我怎樣才能修改這一端
初始花程序,使他一運行,就設置開門狗?
可以在startup.a51中加入看門狗刷新指令,當然用匯編,然後重新編譯startup.a51
,將他和你的程序連接即可。新的startup.a51會自動代替系統默認的啟動模塊。
二十三、keil C51 怎樣把修改的startup.a51 加到工程文件中
直接加入即可
注意不要改動?STACK,?C_START,?C_STARTUP等符號。startup.a51直接加入項目,不用修改也可。可在內面自己修改匯編的一些限制或堆棧指針。
二十四、關於波特率的設置
我在設定串口波特率時發現一個問題:在晶體震盪器為11.0592MHz時,若設9600BPS的話,
TH1=0XFD,TL1=0XFD,而要設19200BPS的話,TH1、TL1有否變化,如果沒變,為什麼?
如果變了,又為什麼?(因為我看書上倆個是一樣的),希望大家點撥。
答:
當電源控制寄存器(PCON)第BIT7(SMOD)為1時波特率加倍。
TH1和TL1的值不變.
二十五、如何在C中聲明保留這部分RAM區不被C使用?
我不知道在C源程序中怎麼控制這個,但在匯編程序中加入下面一段就行:
DSEG AT 20H
AA: DS 10
這樣C51就不會佔用20H--29H了
或者在c51里這樣定義:
uchar data asm_buff[10] _at_ 0x20;
二十六、問浮點運算問題
我在用C51時發現它對傳遞浮點參數的個數有限制,請問:
1)參數是以全局變數的形式傳遞的,請問以全局變數的形式傳遞的參數也有限制嗎?
2)這種傳遞浮點參數的限制有多少呢?
3)float*float的結果是float類型還是double類型?能否直接賦值給float類型的變數?
答:
由於KEIL C51的參數傳遞是通過R0-R7來傳遞的,所以會有限制。
不過KEIL提供了一個編譯參數,可以支持更多參數的傳遞。具體
的內容見KEIL的PDF文檔。
我建議你把多個要傳遞的參數定義到指針或結構體中去,傳遞參
數通過指針或結構進行,這樣好一些。
第3個問題回答是YES,你自己試試不就知道了。
二十七、如何在某一個地址定義ram
用_at_ 命令,這樣可以定位靈活一點的地址
uchar xdata dis_buff[16] _at_ 0x6020 ;//定位RAM
將dis_buff[16]定位在0x6020開始的16個位元組
二十八、keil c中,用什麼函數可以得到奇偶校驗位?
例如32位數據,將四個位元組相互異或後檢查P即可,若耽心P被改變,可用內嵌匯編。
#include
unsigned char parity(unsigned char x){
x^=x;
if(P)return(1);
else return(0);
}
unsigned char parity2(unsigned int x){
#pragma asm
mov a,r7
xrl ar6,a
#pragma endasm
if(P)return(1);
else return(0);
}
2. C++&c語言高手幫忙
#include<iostream>
#include<cstdlib>
using namespace std;
int main(int argc,char* argv[])
{
int n,m,max=0,maxindex,k,beginindex,*action;
cout<<"請輸入n,k:";
cin>>n;
cin>>k;
action=new int[n];
cout<<"請輸入"<<n<<"個eggache值"<<endl;
for(int i=0;i<n;i++)
{
cin>>action[i];
}
for(int i=0;i<n;i++)
{
m=1;
beginindex=i;
for(int j=i+1;j<n;j++)
{
if(abs(action[j])-abs(action[j-1])>k)
{
break;
}
m++;
}
if(m>max)
{
max=m;
maxindex=beginindex;
}
}
cout<<"max="<<max<<endl;
for(int i=maxindex;i<maxindex+max;i++)
{
cout<<action[i]<<" ";
}
cout<<endl;
delete [] action;
system("PAUSE");
return EXIT_SUCCESS;
}
3. C語言大作業.
輸入十名顧客的信息到結構體數組中,最後統計這十名中購買商品總額最大的顧客,將他的信息列印輸出。
//並按照下列各式把信息存入到customer.txt中:
//0001 Kate 5 822.8
//0002 Jame 7 2761.9
//2011.1.11 11:37
#include<stdio.h>
#include<math.h>
#define CST_NUM 10//宏定義客戶數目
struct customer
{
int num;
char name[20];
int amount;
float value;
}cst[CST_NUM];//定義結構體customer,並聲明結構體數組cst[CST_NUM].
void printline(void);
void sort_cst(struct customer[],int);
void print_cst(struct customer[],int);
void main(void)
{
FILE *f1;//聲明文件指針
int h=sin(0);//為編譯器裝載float類型
int i;
for(i=0;i<CST_NUM;i++)//從鍵盤讀取客戶信息
{
printline();
printf("請輸入第%d名顧客的編號",i+1);
scanf("%d",&cst[i].num);
putchar('\n');
fflush(stdin);//清流
printf("請輸入第%d名顧客的姓名",i+1);
scanf("%s",cst[i].name);
putchar('\n');
fflush(stdin);//清流
printf("請輸入第%d名顧客的商品數量",i+1);
scanf("%d",&cst[i].amount);
putchar('\n');
printf("請輸入第%d名顧客的商品總額",i+1);
scanf("%f",&cst[i].value);
putchar('\n');
fflush(stdin);//清流
}
sort_cst(cst,CST_NUM);//客戶信息排序
print_cst(cst,CST_NUM);//將客戶信息輸出至屏幕
f1=fopen("customer.txt","w");//打開文件
fprintf(f1,"客戶編號 客戶姓名 商品數量 商品總額\n");
for(i=0;i<CST_NUM;i++)
{
fprintf(f1,"%5d%12s%10d%10.1f\n",cst[i].num,cst[i].name,cst[i].amount,cst[i].value);//存入客戶信息
}
fclose(f1);//關閉文件
getch();
}
void sort_cst(struct customer cst[],int cst_num)//自定義函數:客戶信息排序
{
int i,j;
struct customer temp;
for(i=0;i<cst_num;i++)
{
for(j=0;j<cst_num;j++)
{
if(cst[i].value>cst[j].value)
{
temp=cst[i];
cst[i]=cst[j];
cst[j]=temp;
}
} }
}
void print_cst(struct customer cst[],int cst_num)//自定義函數:客戶信息顯示
{
int i;
printline();
printf("客戶編號 客戶姓名 商品數量 商品總額\n");
for(i=0;i<cst_num;i++)
{
printf("%5d",cst[i].num);
printf("%12s",cst[i].name);
printf("%10d",cst[i].amount);
printf("%10.1f\n",cst[i].value);
}
printline();
}
void printline(void)//自定義函數:畫線
{
int i;
printf("\n");
for(i=0;i<50;i++)
{
printf("_");
}
printf("\n");
}
4. c語言求解釋
兩個的<<表示按位操作,就是一個二進制數把每一位都往左移動。
如果它是int型的,普通電腦上一般就是4位元組,就是32個bit,就是:
00000000 00000000 00000000 00000001
然後如果r=2那麼1<<r就變成了:
00000000 00000000 00000000 00000100
&表示按位與,而&&表示「並且」或者「同時成立」
按位與可以理解為每一位做乘法
如果rst是4的話,那麼就是
00000000 00000000 00000000 00000100
那麼它與
00000000 00000000 00000000 00000100
按位相乘,結果還是
00000000 00000000 00000000 00000100
如果是
00000000 00000000 00000000 00000100
與
11111111 11111111 11111111 11111111
按位相乘,結果還是
00000000 00000000 00000000 00000100
因為零和零相乘是零
於是當rst的右邊第r+1位是1時,或者cst的右邊第c+1位是1的時候,就返回false
否則返回true
5. 跪求大神幫忙寫一個c語言程序,要求是實現兩個離散數字信號的加減乘除。
數字存儲示波器獲取的是固定時間間隔(窗口)Y軸信號幅值,兩個信號的相加減完成信號的疊加功能,但兩個信號的乘除的物理意義又是什麼呢?
6. 可以作為C語言標識符的是
A, void ,define 是關鍵字,不能作為標識符,C,橫線開頭的不能作為標識符,下劃線開頭的可以,D,數字開頭的不能作為標識符,總結:以字母和下滑線開頭的可以作為標識符
7. C語言使用指定函數去除重復串
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*把結果存到第三個字串*/
void PartString(char *Str1,char *Str2,char *Str3)
{
char *s=Str1,*p=Str3;
int len1=strlen(Str1),len2=strlen(Str2);
int n;
for(s=Str1;s<Str1+len1-len2;)
{
if(strncmp(s,Str2,len2))
{
*p++=*s++;
}
else
{
s+=len2;
}
}
for(;s<Str1+len1;)
{
*p++=*s++;
}
*p='\0';
}
/*直接在字串1中剔除字串2*/
char* PartoutString(char *Str1,char *Str2)
{
char *s=Str1,buffer[30],*p=buffer;
int len1=strlen(Str1),len2=strlen(Str2);
int n;
for(s=Str1;s<Str1+len1-len2;)
{
if(strncmp(s,Str2,len2))
{
*p++=*s++;
}
else
{
s+=len2;
}
}
for(;s<Str1+len1;)
{
*p++=*s++;
}
*p='\0';
strcpy(Str1,buffer);
return Str1;
}
int main(void)
{
char Str[]="ABCDEFAABCFGH";
char SubStr[]="ABC";
char PartStr[30];
printf("%s\n",Str);
printf("%s\n",SubStr);
PartString(Str,SubStr,PartStr);
printf("%s\n",PartStr);
printf("\n");
PartoutString(Str,SubStr);
printf("%s\n",PartStr);
system("pause");
return 0;
}
8. c語言編的匯款系統
摟主寫這個程序干嗎?
這個匯款系統有什麼意義!
除了計算出你所交的匯費以外,貌似沒有別的用途。
9. 幫助編寫一個c語言程序 微型命令解釋程序
一般地可以從標准輸入中讀取字元串
然後通過正則表達式或者手工匹配對字元串進行解析
首先解析指令
然後再解析指令的參數
最後根據指令和參數再通過相應操作系統提供的api來完成相關任務
下面是一個簡單的c語言例子
解析的操作在各平台都是一樣的
我這里以linux平台為基礎做一個例子(該程序是可移植的)
首先定義命令操作的一些介面頭文件(fos.h)
#ifndef_FOS_H
#define_FOS_H
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dirent.h>
#include<sys/types.h>
#include<errno.h>
#include<sys/stat.h>
#defineBUF2048
#defineMAX_PATH512
voidshow_dir(void);
int_file(char*from,char*to,mode_tmode);
int(char*file,char*old_path,char*to,mode_tmode,
uid_tuid,gid_tgid);
int_dir(char*old_path,char*to);
intremove_file(char*filename);
intremove_dir(char*filename);
#endif
然後實現各介面(fos.c)
#include"fos.h"
#defineJMP((strcmp(dir->d_name,".")==0)||(strcmp(dir->d_name,"..")==0))
voidshow_dir(void)
{
DIR*dirp;
structdirent*dir;
dirp=opendir(".");
if(dirp==NULL)
return;
while((dir=readdir(dirp))!=NULL)
printf("%s ",dir->d_name);
closedir(dirp);
}
int_file(char*from,char*to,mode_tmode)
{
intin,out;
charbuf[BUF];
size_tn;
if((in=open(from,O_RDONLY))==-1)
return-1;
if((out=open(to,O_CREAT|O_WRONLY,mode))==-1)
{
close(in);
return-1;
}
while((n=read(in,buf,sizeof(buf)))>0)
write(out,buf,n);
close(in);
close(out);
if(n==-1)
return-1;
return0;
}
int(char*file,char*old_path,char*to,mode_tmode,
uid_tuid,gid_tgid)
{
intin,out;
charbuf[BUF];
size_tn;
if((in=open(file,O_RDONLY))==-1)
return-1;
if(chdir(to)==-1)
{
close(in);
return-1;
}
if((out=open(file,O_CREAT|O_WRONLY,mode))==-1)
{
close(in);
return-1;
}
chown(file,uid,gid);
while((n=read(in,buf,sizeof(buf)))>0)
write(out,buf,n);
close(in);
close(out);
if(n==-1)
return-1;
if(chdir(old_path)==-1)
return-1;
return0;
}
int_dir(char*old_path,char*to)
{
DIR*dirp;
structdirent*dir;
charbuf[MAX_PATH];
structstatmode;
char*current;
charnew_path[MAX_PATH];
if((dirp=opendir(old_path))==NULL)
return-1;
if(chdir(old_path)==-1)
{
closedir(dirp);
return-1;
}
if((current=getcwd(NULL,0))==NULL)
{
closedir(dirp);
return-1;
}
while((dir=readdir(dirp))!=NULL)
{
if(JMP)
continue;
if(stat(dir->d_name,&mode)==-1)
{
perror(dir->d_name);
continue;
}
if(S_ISDIR(mode.st_mode))
{
if(chdir(to)==-1)
continue;
if(mkdir(dir->d_name,mode.st_mode)==-1)
continue;
chown(dir->d_name,mode.st_uid,mode.st_gid);
if(chdir(current)==-1)
continue;
snprintf(new_path,sizeof(new_path),"%s/%s",to,dir->d_name);
if(_dir(dir->d_name,new_path)==-1)
continue;
}
else
{
if((dir->d_name,current,to,mode.st_mode,mode.st_uid,mode.st_gid)==-1)
continue;
}
}
free(current);
closedir(dirp);
if(chdir("..")==-1)
return-1;
return0;
}
intremove_file(char*filename)
{
structstatbuf;
if(stat(filename,&buf)==-1)
return-1;
if(S_ISDIR(buf.st_mode))
remove_dir(filename);
else
returnremove(filename);
}
intremove_dir(char*filename)
{
DIR*dirp;
structdirent*dir;
structstatbuf;
if(rmdir(filename)!=-1)
return0;
if((dirp=opendir(filename))==NULL)
return-1;
chdir(filename);
while((dir=readdir(dirp))!=NULL)
{
if(JMP)
continue;
stat(dir->d_name,&buf);
if(S_ISDIR(buf.st_mode))
remove_dir(dir->d_name);
else
remove(dir->d_name);
}
closedir(dirp);
chdir("..");
rmdir(filename);
return0;
}
接著我們就可以讀入數據並解析命令行了
#include"fos.h"
#defineSHOW_DIR0
#defineCOPY_FILE1
#defineDELETE_FILE2
#defineSHOW_STR3
#defineEXIT4
#defineERROR-1
#defineTEST_CMD(c,n,s,f)
{
if(strncmp(cmd,c,n)==0)
{
cmd+=n;
while(*cmd!=''&&*cmd)
++cmd;
if(*cmd=='')
{
while(*cmd=='')
++cmd;
snprintf(args,512,"%s",cmd);
returns;
}
if(f)
returns;
}
}
intparse_cmd(char*cmd,char*args)
{
TEST_CMD("cdir",4,SHOW_DIR,1);
TEST_CMD("c",5,COPY_FILE,0);
TEST_CMD("cerase",6,DELETE_FILE,0);
TEST_CMD("Cdis",4,SHOW_STR,0);
TEST_CMD("Cend",4,EXIT,1);
returnERROR;
}
intmain(intargc,char**argv)
{
charcmd[1024];
charargs[512];
char*p;
structstatbuf;
size_tn;
while(1)
{
//memset(cmd,0,sizeof(cmd));
printf(">");
fflush(stdout);
n=read(STDIN_FILENO,cmd,sizeof(cmd)-1);
cmd[n-1]='