★求解C语言带参宏定义(关于51单片机定时器的)

★求解C语言带参宏定义(关于51单片机定时器的),第1张

mTimer0set是一个自己写的子程序,用来设置定时器0的溢出机器周期,比如你设X=4000,就是4000个机器周期后溢出,加括号是因为,65535-x的优先度较低,不加括号他就先算%或者/了

aa=11111110;

这句话不对,你这个不是二进制,是10进制,也就是说,你的aa 基实等于:11111110转换成二进制后,取低8位的值,所以aa等于二进制的 11000110,所以会有四个
就我用过的编译器,只有AVR系列的可以直接用进制,其它的没有二进制的形式

AVR Studio可以用 aa = 0b 11111110表示二进制,Keil没有扩展0b,所以不能用二进制表示
只能用宏转换
#define LongToBin(n)\
(\
((n >> 21) & 0x80)| \
((n >> 18) & 0x40)| \
((n >> 15) & 0x20)| \
((n >> 12) & 0x10)| \
((n >> 9) & 0x08)| \
((n >> 6) & 0x04)| \
((n >> 3) & 0x02)| \
((n ) & 0x01) \
)

你可以这样写 aa=LongToBin(11111110);
这样,十进制的 11111110就被转换成 二进制的 11111110,你还可以把 0-255之间的所有数字都定义成宏,因为数量太多,我就不给你写出来了,给你个参考资料地址
>宏定义本质上是C语言提供的预处理命令,并不是什么单片机名词。通俗的说宏就是替代符号,比如说你要定义一个人的年龄变量,在程序中你可以用#define age unsigned char。这样你在程序中所能用到关于年龄的变量就可以这样age XiJiping。对于一个复杂的程序,灵活运用宏定义可以让你的程序更易读,移植起来也会更容易。

1、首先注意51单片机上电的时候会有个复位的 *** 作,复位的时候不执行单片机内部程序,复位之后51单片机的所有IO口都为高电平;
2、在单片机复位之后在main函数里执行程序,如果要使Io口初始化为低电平,就要在while循环的上方把IO置低;例如:
一般程序的结构是这样的:
void main()
{

IO = 0 ; //在while的上方对IO置低,

while(1)
{
}
}
3、基于上面的原理,在设计单片机外围电路的时候,为了不让外围电路误动作,一般把外围电路设置成单片机IO口低电平的时候 尽心动作,
比如: 点亮LEd灯的时候,,一般把LEd的负极接IO口,,这样单片机上电的时候,没有进入程序之前,LED是不会亮的,

*** 作特殊功能寄存器必须事先声明,如:
sfr P0 = 0x80;
sbit P11 = 0x91;
#define 只是进行一次宏定义, 在程序中遇到 chargecurrent 时就将此替换为数值0xec
此处
0xec仅仅是一个数据,此处不能写寄存器地址, 不过可以写在其它地方定义过的标号比如
#define P11 P23 就是将P11替换为P23(如果定义了P11为P11,P23为P23的情况下)

//
//实现功能:本程序实现在P1口模拟一个流水灯程序
//
#include <reg51h>
#define p_out P1 //宏定义输出的i/o口为P1
//时间延迟函数
//描 述:用指令实现延时一段时间
//入口参数:int i,为时间延迟参数
//
void delay_time(int i)
{
while(i)
i--;
}
//主函数
//描 述:实现在P1口模拟一个流水灯程序
//
void main(void)
{unsigned char i=0; //初始化一个局部变量为0
p_out=0xff; //初始化将要输出的i/o口,输出高电平,熄灭所有灯
while(1)
{
for(i=0;i<8;i++)
{
p_out=~(1<<i);//点亮一个灯,
delay_time(50000); //延迟一段时间
p_out=0xff;//熄灭所有灯
}
}
}
//
//
//实现功能:把键盘输入的键盘码,用led显示出来
//
#include <reg51h>
#define p_key P1
#define led_date P0
#define choose_p P2
unsigned char change(unsigned char i);
unsigned int display_num=0;
//时间延迟函数
//描 述:用指令实现延时一段时间
//入口参数:int i,为时间延迟参数
//
void delay_time(int i)
{
while(i)
i--;
}
//按键扫描函数
//描 述:对44键盘进行扫描,程序只适合44键盘使用,
// 键盘占用一组完整的i/o口,在使用这个程序前
// 要宏定义p_key为用户实际连接键盘的i/o口
// #define p_key Pn;//(n=0、1、2、3)
//返回参数:若有检测到按键就返回按键的编号,否则返回0xff
//
unsigned char read_key(void)
{
unsigned char j,key,key_buf=0;
p_key=0xff;
//检测是否有建按下//
p_key=0xf0;
key=p_key;
if(key==0xf0)
{
return(0xff);//没按键按下,返回0xff
}
//有按下,延时去抖//
delay_time(5000);
//确认是否有建按下//
p_key=0xf0;
key=p_key;
if(key==0xf0)
{
return(0xff);//没按键按下,返回0xff
}
//真的有按键按下,扫描是哪一行有按键按下//
for(j=0;j<4;j++)
{key=p_key&(0x10<<j);
if (key)
{
key=p_key;
}
else
{
key_buf=j4;
p_key=~(0x10<<j);//第j行的按键按下了,第j行输出0,其他的i/o口输出1
//扫描是第j行的哪个按键按下//
for(j=0;j<4;j++)
{
key=p_key&(1<<j);
if (key)
{
key=p_key;
}
else
{
key_buf+=j;
return(key_buf);//扫描到按键的确定位置,返回按键的编号
}
}
}
}
//没扫描到按键,//
return(0xff);
}
//七段数码管显示函数
//描 述:对四位的扫描型七段数码管进行扫描显示,在使用
// 前要定义一个全局变量display_num
// unsigned int display_num;
//入口参数:unsigned int num,要显示的数字(0-9999)
//
void display(unsigned int num)
{
if(num<10000)
{
display_num=num;
}
choose_p|=3;//先关显示
led_date=change(display_num/1000);//得到千位的数字,并转换成七段码型
choose_p&=0xfe;//选通千位
delay_time(50);//延时一段时间
choose_p|=1;//关显示
display_num=display_num%1000;
led_date=change(display_num/100);//得到百位的数字,并转换成七段码型
choose_p&=0xfd;//选通百位
delay_time(50);//延时一段时间
choose_p|=2;//关显示
display_num=display_num%100;
led_date=change(display_num/10);//得到十位的数字,并转换成七段码型
choose_p&=0xfb;//选通十位
delay_time(50);//延时一段时间
choose_p|=4;//关显示
led_date=change(display_num%10);//得到个位的数字,并转换成七段码型
choose_p&=0xf7;//选通十位
delay_time(50);//延时一段时间
choose_p|=8;//关显示
}
//数字-码型转换函数
//描 述:把数字转换成七段码型,此程序仅配合共阳的七
// 段数码管使用
//入口参数:unsigned char i,要转换的数字(0-9),
//返回参数:转换后的七段码型,0xff表示转换失败
//
unsigned char change(unsigned char i)
{
switch(i)
{
case 0:
return(0xc0);//0的七段码型
case 1:
return(0xf9);//1的七段码型
case 2:
return(0xa4);//2的七段码型
case 3:
return(0xb0);//3的七段码型
case 4:
return(0x99);//4的七段码型
case 5:
return(0x92);//5的七段码型
case 6:
return(0x82);//6的七段码型
case 7:
return(0xf8);//7的七段码型
case 8:
return(0x80);//8的七段码型
case 9:
return(0x90);//9的七段码型
default:
return(0xff);//转换失败
}
}
//主函数
//描 述:把键盘输入的键盘码,用led显示出来
//
int main(void)
{unsigned char i;
while(1)
{
i=read_key();//扫描键盘
if(i<16)
display((unsigned int)i);//有效的键盘值
else
display(0xffff);//数据无效
}
}
//两个程序加起来就可以完成你要求的功能,有说明,你认真看一下吧。

#define E2P_RECORD_ADDR 0x00
#define POWER_UP_MARK 0xAB
是预编译,就是在告诉编译器: E2P_RECORD_ADDR=0x00,POWER_UP_MARK=0xAB;
编译器在编译你的程序之前,在你的代码里寻找,遇到 E2P_RECORD_ADDR 这个名字就把它替换成0x00, 遇到 POWER_UP_MARK 这个名字就把它替换成0xAB;
这就叫预编译。
结构体struct是一种数据类型,同 int 或 char 一样,它是一种数据类型,不同的是结构体是你自定义的,而int和char是系统自带的,你可以把它想象成和 int 、char 一样的东西,不过它是由你设计的。比如 定义一个结构体类型 ——“人”这个类型,每个人都有名字,同时人都有年龄,那么你可以这样定义:
typedef struct {
string name;
char age;
}HUMAN;
那么HUMAN就是一个类型名,同int、char一样,它是“人”这个类型,可以用这个类型名定义实体变量:
struct HUMAN zhangsan;
struct HUMAN lisi;
这里“struct HUMAN”就相当于“int”或“char“,这时zhangsan、lisi就是一个结构体变量了,它们都有name和age这两个属性了,可以对它们进行 *** 作:
比如张三10岁,李四20岁,可以这样:
zhangsanage=10;
lisiage=20;


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/10322974.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-07
下一篇 2023-05-07

发表评论

登录后才能评论

评论列表(0条)

保存