① 单片机中,用c语言对at24c02进行操作时,判断应答信号是否有效时,有效则return(0),返回0有什么用
#ifndef __AT24C02_H__
#define __AT24C02_H__
#include<stc89.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含NOP空指令的头文件
#define uchar unsigned char
#define uint unsigned int
/*宏定义器件地址*/ //AT24C器件ID 1 0 1 0 A2 A1 A0 RW
#define AT24_ID0 0XA0 //AT24C器件ID 1 0 1 0 0 0 0 RW
#define AT24_ID1 0XA2 //AT24C器件ID 1 0 1 0 0 0 1 RW
#define AT24_ID2 0XA4 //AT24C器件ID 1 0 1 0 0 1 0 RW
#define AT24_ID3 0XA6 //AT24C器件ID 1 0 1 0 0 1 1 RW
#define AT24_ID4 0XA8 //AT24C器件ID 1 0 1 0 1 0 0 RW
#define AT24_ID5 0XAA //AT24C器件ID 1 0 1 0 1 0 1 RW
#define AT24_ID6 0XAE //AT24C器件ID 1 0 1 0 1 1 1 RW
/*其他参数*/
#define AT24_INQ 255 //器件应答最大检测次数 超过此数量 无应答也会退出循环 以避免程序死循环
/*I2C总线驱动IO口*/
sbit I2C_SCL=P1^5;//串行时钟输入。SCL同步数据传输,上升沿数据写入,下降沿数据读出
sbit I2C_SDA=P3^6;//穿行地址和数据输入/输出。SDA是双向串行数据传输引脚,漏极开路,需外接上拉电阻到VCC(典型值10K)
/*最终使用的函数*/
void at24cxx_weite(uchar I2C_IDRW,I2C_ADDRESS,I2C_DATA);//写入AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址 I2C_DATA数据
uchar at24cxx_read(uchar I2C_IDRW,I2C_ADDRESS) ; //带地址的读取AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址
/*被调用的子函数*/
uchar at24cxx_rd(I2C_IDRD); //当前地址读取AT24 由 读取函数调用 I2C_IDRD 为器件地址
void at24cxx_com(uchar I2C_DATA); //AT24写公用函数 由写入读取函数调用 I2C_DATA 为要写入的变量(器件ID,数据地址,数据)
void at24cxx_start(); //AT24起始信号 由写入读取函数调用
void at24cxx_stop(); //AT24停止信号 由写入读取函数调用
void at24cxx_inquires(uchar I2C_IDRW);//AT24应答检测 由写入读取函数调用
void at24cxx_response(); //I2C总线应答检测 由写入读取函数调用
void at24cxx_ricom(); //器件应答与总线应答检测 公用函数 由器件应答和总线应答函数调用
/*字节写操作 起始条件 器件地址 写 字地址 数据停止条件*/
void at24cxx_weite(uchar I2C_IDRW,I2C_ADDRESS,I2C_DATA)//写入AT24I2C_IDRW器件地址 I2C_ADDRESS数据地址 I2C_DATA数据
{
//at24cxx_start(); //起始条件 开始写入数据
//at24cxx_com(I2C_IDRW&0xfe); //写入芯片ID及读写选择位 0
//at24cxx_response(); //总线应答
at24cxx_inquires(I2C_IDRW&0xfe);//器件应答检测 并写入器件ID以及读写选项 内部有起始条件
at24cxx_com(I2C_ADDRESS); //写入数据地址
at24cxx_response(); //总线应答
at24cxx_com(I2C_DATA); //写入数据
at24cxx_response(); //总线应答
at24cxx_stop(); //结束条件 终止写入数据
}
/*函数流程 起始条件 器件地址 写 字地址 起始条件 器件地址 读 读数据 停止条件*/
uchar at24cxx_read(uchar I2C_IDRW,I2C_ADDRESS) //带地址的读取AT24 I2C_IDRW器件地址 I2C_ADDRESS数据地址
{ uchar I2C_DATA; //最终读取的数据
//at24cxx_start(); //起始条件 开始写入数据
//at24cxx_com(I2C_IDRW&0xfe); //写入芯片ID及读写选择位 0
//at24cxx_response(); //总线应答
at24cxx_inquires(I2C_IDRW&0xfe); //器件应答检测 并写入器件ID以及读写选项 内部有起始条件
at24cxx_com(I2C_ADDRESS); //写入数据地址
at24cxx_response(); //总线应答
I2C_DATA=at24cxx_rd(I2C_IDRW|0x01);//写入芯片ID及读写选择位 1 程序内部有起始停止功能
return(I2C_DATA); //返回数据
}
/*起始条件 器件地址 读 数据 停止条件*/
/*当前地址读 起始条件 器件地址 读 数据 停止条件*/
/*接收器件地址(读/写选择为为1)、EEPROM应答ACK后,当前地址的数据就随时钟送出主器件无需应答0,但需要发送停止条件*/
uchar at24cxx_rd(I2C_IDRD) //当前地址读取AT24 I2C_IDRD为器件地址
{ uchar I2C_NUM,I2C_DAT; //定义8位变量用来做循环移位读取数据
at24cxx_start(); //起始条件
at24cxx_com(I2C_IDRD|0x01); //写入芯片ID及读写选择位 1
at24cxx_response(); //总线应答
for(I2C_NUM=0;I2C_NUM<8;I2C_NUM++)
{ I2C_DAT=I2C_DAT<<1; //数据左移位
I2C_SCL=1; //拉高时钟线得到 要读的数据
_nop_(); //一个机器周期指令
if(I2C_SDA==1) //判断数据为1
{I2C_DAT=I2C_DAT|0X01;} //将数据变量赋值
I2C_SCL=0; //拉低时钟线 以获得新数据
nop_(); //一个机器周期指令
}
at24cxx_stop(); //结束条件 终止接收数据
return(I2C_DAT); //返回数据
}
/*由读写函数调用 目的:节省空间*/
void at24cxx_com(uchar I2C_DATA) //AT24写公用函数
{ uchar I2C_NUM,I2C_DAT; //定义8位变量用来做循环写入位
for(I2C_NUM=0;I2C_NUM<8;I2C_NUM++)
{
I2C_DAT=(I2C_DATA>>7);//获得数据最高位
I2C_DAT=I2C_DAT&0X01; //取数据的最高位数据
I2C_SCL=0; //拉低时钟线数据传输开始
_nop_(); //一个机器周期指令
I2C_SDA=I2C_DAT; //I2C数据线赋值
_nop_(); //一个机器周期指令
I2C_SCL=1; //拉高时钟线数据存储
_nop_(); //一个机器周期指令
I2C_DATA=I2C_DATA<<1; //数据移位
}
}
/*当SCL为高电平时SDA的下降沿(高到低)叫做起始条件(START)起始条件保持时间 最小值1.8V 0.6US:5V 0.25US 起始条件建立时间1.8V 0.6US:5V 0.25US */
void at24cxx_start()//AT24起始信号
{
I2C_SCL=1; //空闲总线
_nop_(); //一个机器周期指令
I2C_SDA=1; //空闲总线
_nop_(); //一个机器周期指令
I2C_SDA=0; //拉低数据线 发起起始信号
_nop_(); //一个机器周期指令
}
/*SDA的上升沿(低到高)叫做停止条件(STOP) 停止条件建立时间 最小值1.8V 0.6US:5V 0.25US */
void at24cxx_stop() //AT24停止信号
{
I2C_SDA=0; //拉低数据线 以便形成上升沿
_nop_(); //一个机器周期指令
I2C_SCL=1; //
_nop_(); //一个机器周期指令
I2C_SDA=1; //老高数据线 发起停止信号
_nop_(); //一个机器周期指令
}
/*一旦内部写周期启动,EEPROM输入无效,此时即可启动应答查询:发送起始条件和器件地址(读/写位为期望的操作)。
只有内部写周期完成EEPROM才会应答“0”。之后可继续读/写操作
应答查询流程:1.发送写命令 2.发送停止条件启动写周期 3.发送起始条件 4.发送控制字节R/W=0 5.器件是否应答(ACK=0)? 是 5.下一操作 否 重复2-4操作
*/
void at24cxx_inquires(uchar I2C_IDRW)//AT24应答查询
{ uchar AT24_NUM; //定义变量用来跳出循环应答检测
AT24_NUM=AT24_INQ; //赋值应答最大检测次数 避免无应答时程序死循环
while(AT24_NUM--) //循环判断应答
{ at24cxx_start(); //发送起始条件
at24cxx_com(I2C_IDRW); //写入芯片ID及读写选择位
at24cxx_ricom(); //调用应答公用检测函数
if(I2C_SDA==0) //应答成功
{break;} //退出循环
}
I2C_SCL=0; //应答结束拉低时钟线
_nop_(); //一个机器周期指令
I2C_SDA=1; //应答结束把数据线重新拉高
_nop_(); //一个机器周期指令
}
/*接收器拉低SDA线表示应答,应在应答脉冲器件保持稳定的低电平。当主器件做接收器时,必须发出数据传输结束的信号给发送器,
即它在最后一个字节之后的应答脉冲期间不会产生应噶信号(不拉低SDA)。这种情况下,发送器必须释放SDA线为高以便主器件产生停止条件*/
void at24cxx_response()//总线应答
{
at24cxx_ricom(); //调用应答公用检测函数
I2C_SCL=0; //应答结束拉低时钟线
_nop_(); //一个机器周期指令
I2C_SDA=1; //应答结束把数据线重新拉高
_nop_(); //一个机器周期指令
}
/*器件应答与总线应答公用函数 由于这部分代码相同 所以写成一个函数 以节省空间*/
void at24cxx_ricom() //器件应答与总线应答检测 公用函数
{
uchar AT24_NUM; //定义变量 用来无应答时跳出循环判断应答
I2C_SCL=0; //总线应答额外脉冲
_nop_(); //一个机器周期指令
I2C_SDA=1; //拉高数据线 以检测应答
_nop_(); //一个机器周期指令
I2C_SCL=1; //应答时钟脉冲
_nop_(); //一个机器周期指令
while(I2C_SDA) //判断应答
{
if(AT24_NUM<255)//判断累加 总线应答检测最大时间(次数) 避免无应答时程序死循环
{AT24_NUM++;} //没有到则自+
else //否则
{break;} //退出循环判断应答
}
}
② 一道C语言题目
不好意思,你的程序结构太乱了,我给你改了一下:
#include<stdio.h>
FILE *fin,*fout;
//输出到文件
void OutputFile(int a[], int count)
{
fprintf(fout,"%2d: ", count);
for(int i = 0; i < 10; i++)
{
fprintf(fout, "%d \t", a[i]);
}
fprintf(fout,"\n");
}
//判断每个战士手中的子弹是否相等
bool Equal(int a[])
{
int t = a[0];
for (int i = 1; i < 10; i ++)
{
if (a[i] != t) return false;
}
return true;
}
void main()
{
fin=fopen("1.in", "r");
fout=fopen("1.out", "w");
int a[10], i;
int o[10]; //保存战士一半的字弹数
int count = 0; //统计圈数
//扫描原始数据
for(i = 0; i < 10; i++)
fscanf(fin, "%d", &a[i]);
//初始化
for(i = 0; i < 10; i++)
o[i] = 0;
//打印原始子弹数
OutputFile(a, count);
//当手中的子弹书不相等继续循环
while(!Equal(a))
{
//如果战士手中子弹为奇数,则向班长要一颗
for( i = 0; i < 10; i++)
{
if(a[i] % 2 == 1) a[i]++;
}
//每个战士减一半
for (i = 0; i < 10; i++)
{
o[i] = (a[i] /= 2);
}
//给下一个战士
for (i = 0; i < 10; i++)
{
a[(i + 1) % 10] += o[i];
}
//输出结果
OutputFile(a, count++);
}
printf("OK\n");
getchar();
fclose(fin);
fclose(fout);
}
输出结果为:
0: 10 2 8 22 16 4 10 6 14 20
0: 15 6 5 15 19 10 7 8 10 17
1: 17 11 6 11 18 15 9 8 9 14
2: 16 15 9 9 15 17 13 9 9 12
3: 14 16 13 10 13 17 16 12 10 11
4: 13 15 15 12 12 16 17 14 11 11
5: 13 15 16 14 12 14 17 16 13 12
6: 13 15 16 15 13 13 16 17 15 13
7: 14 15 16 16 15 14 15 17 17 15
8: 15 15 16 16 16 15 15 17 18 17
9: 17 16 16 16 16 16 16 17 18 18
10: 18 17 16 16 16 16 16 17 18 18
11: 18 18 17 16 16 16 16 17 18 18
12: 18 18 18 17 16 16 16 17 18 18
13: 18 18 18 18 17 16 16 17 18 18
14: 18 18 18 18 18 17 16 17 18 18
15: 18 18 18 18 18 18 17 17 18 18
16: 18 18 18 18 18 18 18 18 18 18
③ 问一个C语言的题目,C高手请进!
同时分一半,是可以实现
结果是:调整17次后,每人的子弹数为18.
#include <stdio.h>
main()
{
int a[10] = {10,2,8,22,16,4,10,6,14,20};
int b[10];
int i;
int flag; /*标志子弹数是否已全相等,1为相等,0为不相等*/
int num = 1; /*表示调整次数*/
while(1)
{
for(i=0;i<10;i++)
{
if(a[i]%2!=0)a[i]+=1;
}
for(i=0;i<10;i++)
{
b[i] = a[i] = a[i]/2;
}
a[0]+=b[9];
for(i=0;i<9;i++)
{
a[i+1]+=b[i];
}
flag = 1;
for(i=0;i<9;i++)
{
if(a[i]!=a[i+1])
{
num++;
flag = 0;
break;
}
}
if(flag == 1)break; /*如果相等,跳出循环*/
}
printf("after do %d times, the num of bullets is same, and everyone has %d\n",num,a[0]);
}
④ 我用c语言写控制台坦克大战,可是子弹发射这里不会了,我本来的想法是定时扫描然后画出子弹,但结果失败
我想看看你的代码,
⑤ C语言:战士分子弹问题
#include<stdio.h>
#include<math.h>
voidmain()
{
inta[10]={10,2,8,22,16,4,10,6,14,20};
intb[10];
intj,k,cout=0;
printf("%d ",cout++);
for(inti=0;i<10;i++)
printf("%d",a[i]);
printf(" ");
while(!(a[0]==a[1]&&a[1]==a[2]&&a[2]==a[3]&&a[3]==a[4]&&a[4]==a[5]&&a[5]==a[6]&&a[6]==a[7]&&a[7]==a[8]&&a[8]==a[9]&&a[9]==a[0]))
{
{
for(j=0;j<10;j++)
{
a[j]=a[j];
if(1==a[j]%2)
a[j]=a[j]+1;
}
for(j=0;j<10;j++)
{
if(j==0)
b[j]=(a[j]+a[9])/2;
else
b[j]=(a[j]+a[j-1])/2;
}
printf("%d ",cout++);
for(k=0;k<10;k++)
{
a[k]=b[k];
printf("%d",a[k]);
}
printf(" ");
}
}
}