关于STC单片机Keil编译器写C代码的部分小技巧2

1、 通常情况下我们的代码量不大的话,没必要去关注RAM的空间,一旦全局变量多,以及代码量大,这种情况下我们就需要关注了。
我们的51系列单片机,使用keil编译器编译时,会发现下方会有三个参数大小,分别是Data,Xdata,Code。
以个人的理解,整体来说,单片机内部空间,可分为变量存储器和代码存储区,即SDRAM和Flash程序存储区。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
即:SDRAM=idata+xdata
data为固定的最大128字节
idata=data+128=256(字节)
xdata则等于单片机规格所拥有的SDRAM-256(字节)
code=Flash程序存储区
所以,需要注意自己的全局变量存储位置,data 和xdata的存放是有不同定义的,个人理解是如果你的变量是需要高速动作的,你就存放于data空间,而某些不是经常使用的变量,你就可以放到xdata空间,例如我个人的一个案例:
我的一个PWM输出函数,是使用定时器生成的,而这个PWM是100Hz的频率,相当于我要给一个100us的定时器来做,那么这个定时器变量就要100us进行一次赋值,这个动作是非常快的,那么我就将这个变量放在了data空间,这样我的PWM的频率是比较准确的,如果我放在了xdata空间,两种情况:要么PWM无法生成,要么频率达不到100HZ左右。

#include "STC8.H"
#define uchar unsigned char
#define uint unsigned int
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned char uint8_t;
typedef unsigned int  uint16_t;

data u8 PWM_C=0;	//PWM用
xdata u8 LED_C=0;	//不常用可放在xdata
data u8 Time0_100usCnt=0;	//定时器0的100us计数
data u8 Time0_1msCnt=0;	//定时器0的1ms计数
data u8 Time0_10msCnt=0;	//定时器0的10ms计数
data u8 Time0_100msCnt=0;	//定时器0的100ms计数

/*函数名称:Timer0Init(void)
 *功能描述:初始化定时器0
 *输入参数:无
 *输出参数:无
 *调用	  :主函数
 */
void Timer0Init(void)		//100微秒@22.1184MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x5C;		//设置定时初值
	TH0 = 0xF7;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;		//开定时器0中断
	EA=1;		//开总中断
}

/*函数名称:timer0(void)
 *功能描述:定时器0中断服务函数
 *输入参数:无
 *输出参数:无
 *调用	  :
 */
void timer0() interrupt 1	//100us
{	
	Time0_100usCnt++;	
	if(Time0_100usCnt>=10)//1ms
	{
		Time0_100usCnt=0;
		Time0_1msCnt++;
		
	}
	if(Time0_1msCnt>=10)//10ms
	{
		Time0_1msCnt=0;
		Time0_10msCnt++;
	}
	if(Time0_10msCnt>=10)//100ms
	{
		Time0_10msCnt=0;
		Time0_100msCnt++;
	}
	if(Time0_100msCnt>10)//1s
	{
		Time0_100msCnt=0;
	}
/***************************************/	
	
	MIC_PWM();
	

}
//****************************************************
/*								PWM								*/
//****************************************************
void MIC_PWM(void)
{

  PWM_C++;
	if(PWM_C==100)		 //100HZ
	{	
		PWM_C=0;		
		if(LED_C==0)	LED_PWM=1;
		else		LED_PWM=0;
	} 
  else
	{

		if(LED_C==WD_C)	LED_PWM=1;
	}

}
void main()
{
	Timer0Init();
	while(1)
	{
		...
	}
}

当然了,你需要看下你的配置的内存模式优先级,如果你选的是DATA,编译器就是默认你定义的变量优先为存储到data空间,当你的代码量大的时候,你需要选择xdata。

在这里插入图片描述在这里插入图片描述

意思是说,当你的代码量足够大,然后你的内存空间满了,可以选择该模式,将你的代码自动优化,不至于写了128个字节变量,就挤爆了。
还要你自己去选哪个变量放那个区。
code区是不可变的,不可改动,一般我们定义一些不可变的数组时,可以在数组前添加code定义到程序存储区,减小ram的压力。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用 STC 单片机 bq27542 的 C 语言代码示例: ```c #include <reg52.h> #define SDA P1_0 #define SCL P1_1 void delay(int n) { // 延时函数 int i, j; for (i = 0; i < n; i++) { for (j = 0; j < 120; j++); } } void start() { // 启动信号 SDA = 1; delay(1); SCL = 1; delay(1); SDA = 0; delay(1); SCL = 0; delay(1); } void stop() { // 停止信号 SDA = 0; delay(1); SCL = 1; delay(1); SDA = 1; delay(1); } void ack() { // 确认信号 SDA = 0; delay(1); SCL = 1; delay(1); SCL = 0; delay(1); SDA = 1; delay(1); } void nack() { // 非确认信号 SDA = 1; delay(1); SCL = 1; delay(1); SCL = 0; delay(1); } void write_byte(unsigned char byte) { // 入一个字节 unsigned char i; for (i = 0; i < 8; i++) { SDA = (byte & 0x80) >> 7; byte <<= 1; delay(1); SCL = 1; delay(1); SCL = 0; delay(1); } } unsigned char read_byte() { // 读取一个字节 unsigned char i, byte = 0; SDA = 1; delay(1); for (i = 0; i < 8; i++) { SCL = 1; delay(1); byte = (byte << 1) | SDA; SCL = 0; delay(1); } return byte; } void write_register(unsigned char reg, unsigned char data) { // 寄存器 start(); write_byte(0xAA); // 发送地址 ack(); write_byte(reg); // 发送寄存器地址 ack(); write_byte(data); // 发送数据 ack(); stop(); } unsigned char read_register(unsigned char reg) { // 读寄存器 unsigned char data; start(); write_byte(0xAA); // 发送地址 ack(); write_byte(reg); // 发送寄存器地址 ack(); start(); write_byte(0xAB); // 发送读取地址 ack(); data = read_byte(); // 读取数据 nack(); stop(); return data; } void main() { unsigned char data; write_register(0x00, 0x00); // 设置保护寄存器 data = read_register(0x0F); // 读取状态寄存器 write_register(0x10, 0x01); // 设置充电电流 write_register(0x11, 0x02); // 设置放电电流 write_register(0x12, 0x03); // 设置容量 write_register(0x13, 0x04); // 设置电压 } ``` 以上代码中,使用 SDA 和 SCL 两个 GPIO 信号线来进行 I2C 通信,通过 `write_register` 和 `read_register` 函数来入和读取 bq27542 的寄存器。需要根据实际情况修改地址、数据等参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值