📄 chip.c
字号:
#include <./Atmel/at89x52.h>
#include <stdio.h>
#include "source.h"
#include <intrins.h>
#include <absacc.h>
//_nop_(); 在fosc=18.432MHZ时,一个空语句是 0.65us
void delay_macnine_ncircle(unsigned char cnt){//11+6*cnt machin circle.
while(cnt--);
}
void delay_10us(unsigned char tus){//在晶振频率为18.432MHZ时延时10微秒的函数
tus--;
while(tus--){
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
}
/*因为AT24C4的最大速率为100k,所以需要延时*/
#define DELAY _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
#define I2CDATA SDA /*for read data from bit port*/
#define I2CSETDATA SDA=1 /*sda=1 macro*/
#define I2CCLRDATA SDA=0 /*sda=0 macro*/
#define I2CSETCLK SCL=1 /*scl=1 macro*/
#define I2CCLRCLK SCL=0 /*scl=0 macro*/
#define i2c_start AT24C64_start
#define i2c_stop AT24C64_stop
#define i2c_write_byte AT24C64_write_byte
#define i2c_read_byte AT24C64_read_byte
#define i2c_wait_ack AT24C64_wait_ack
#define i2c_send_ack AT24C64_send_ack
#define i2c_send_notack AT24C64_send_notack
/***以下的函数与SDA2000的操作是一样的,而使用的端口也是一样的***/
void i2c_start(){
I2CSETDATA;
I2CSETCLK;
DELAY;
I2CCLRDATA;
DELAY;
I2CCLRCLK;
}
void i2c_stop(){
I2CCLRCLK;
I2CCLRDATA;
DELAY;
I2CSETCLK;
DELAY;
I2CSETDATA;
}
void i2c_write_byte(unsigned char ch)
{
unsigned char i=8;
while(i--){
I2CCLRCLK;_nop_();
if(ch&0x80)
I2CSETDATA;
else
I2CCLRDATA;
ch<<=1;DELAY;
I2CSETCLK;DELAY;
}
I2CCLRCLK;
}
unsigned char i2c_read_byte(void)
{
unsigned char i=8;
unsigned char ddata=0;
I2CSETDATA ;
while (i--){
ddata<<=1 ;
I2CCLRCLK;DELAY;
I2CSETCLK;DELAY;
ddata|=I2CDATA;
}
I2CCLRCLK;
return ddata;
}
bit i2c_wait_ack(void)
{
unsigned char errtime=255;//因故障接收方无ACK 超时值为255
I2CSETDATA;DELAY;
I2CSETCLK ;DELAY;
while(I2CDATA){
errtime--;
if (!errtime){
i2c_stop();
return 0;
}
}
I2CCLRCLK;
return 1;
}
void i2c_send_ack(void)
{
I2CCLRDATA; DELAY;
I2CSETCLK; DELAY;
I2CCLRCLK;
}
void i2c_send_notack(void)
{
I2CSETDATA ; DELAY;
I2CSETCLK ; DELAY;
I2CCLRCLK;
}
/***因为AT24C64与SDA2000共用同样的CPU管脚,其区分对不同芯片的操作是使用设备类型**/
/***来区分的,如EEPROM的地址为0xa,而SDA2000的设备地址为0x6*/
#define DEVICEAW 0Xa0
#define DEVICEAR 0Xa1
void AT24C64_wbytes(unsigned char *add,unsigned char len,unsigned char *buf){//向EEPROM中写数据,最长为32个字节
unsigned char hadd,ladd;
unsigned char i;
hadd=add[0];
ladd=add[1];
AT24C64_start();
AT24C64_write_byte(DEVICEAW);
AT24C64_wait_ack();
AT24C64_write_byte(hadd);
AT24C64_wait_ack();
AT24C64_write_byte(ladd);
AT24C64_wait_ack();
for(i=0;i<len;i++){
AT24C64_write_byte(buf[i]);
AT24C64_wait_ack();
}
AT24C64_stop();
delay_10us(100);//因为EEPROM在写下一个数据时要等待5ms.
delay_10us(100);
delay_10us(100);
delay_10us(100);
delay_10us(100);//延时了5ms.
}
void AT24C64_rbytes(unsigned char *add,unsigned char len,unsigned char *buf){//为读EEPROM中的字节
unsigned char hadd,ladd;
unsigned char i;
hadd=add[0];
ladd=add[1];
AT24C64_start();
AT24C64_write_byte(DEVICEAW);
AT24C64_wait_ack();
AT24C64_write_byte(hadd);
AT24C64_wait_ack();
AT24C64_write_byte(ladd);
AT24C64_wait_ack();
for(i=0;i<len;i++){
AT24C64_start();
AT24C64_write_byte(DEVICEAR);
AT24C64_wait_ack();
buf[i]=AT24C64_read_byte();
}
AT24C64_stop();
}
void init_eeprom(void){//把EEPROM的内容都初始化为0
unsigned char temp;
unsigned int add;
temp=0;
for(add=0;add<8192;add++){
AT24C64_wbytes((unsigned char *)&add,1,&temp);
}
}
#define ULWRCYCLE FLASHADD=0X00;XBYTE[0XCAAA]=0XAA;XBYTE[0XC555]=0X55
#define WRITE_CMD ULWRCYCLE;FLASHADD=0X00;XBYTE[0XCAAA]=0XA0
#define ERASE_CMD ULWRCYCLE;FLASHADD=0X00;XBYTE[0XCAAA]=0X80;ULWRCYCLE
#define ERASE_CHIP ERASE_CMD;FLASHADD=0X00;XBYTE[0XCAAA]=0X10
bit erase_sector(unsigned char sa){//擦除flash扇区
unsigned int n;
unsigned char cnt;
unsigned char temp;
unsigned char rybystat;
ERASE_CMD;
temp=sa;
if(sa<8){//每个扇区是8K字节
cnt=temp;
temp >>=1;
FLASHADD=temp;
if(cnt%2){
XBYTE[0X2000+FLASH_SPACE_START]=0X30;//擦除扇区命令.
}
else{
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇区命令.
}
}
else{//每个扇区是64k字节
cnt=temp-7;
temp=cnt <<2;
FLASHADD=temp;
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇区命令.
}
rybystat=FLASHRYNBY;
for(n=0;n<2000;n++){
if(rybystat&0x01==0x00){//开始擦除.
goto my_exit;
}
rybystat=FLASHRYNBY;
}
my_exit:
while(1){
rybystat=FLASHRYNBY;
if(rybystat&0x01==0x01){
break;
}
}
if(cnt>=2000){
return 0;//不能开始擦除
}
return 1;
}
void erase_flash(unsigned char flag,unsigned char sa){
unsigned char cnt;
unsigned char temp;
unsigned char rybystat;
if(flag==0){
ERASE_CHIP;
// Erase all chip.
}
else{
ERASE_CMD;
temp=sa;
if(sa<8){// boot 扇区,每个扇区是8k字节.
cnt=temp;
temp >>=1;
FLASHADD=temp;
if(cnt%2){
XBYTE[0X2000+FLASH_SPACE_START]=0X30;//擦除扇区命令.
}
else{
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇区命令.
}
}
else{//it is 64k pre sector.
cnt=temp-7;
temp=cnt <<2;
FLASHADD=temp;
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇区命令.
}
}
for(cnt=0;cnt<250;cnt++){
rybystat=FLASHRYNBY;
if((rybystat&0x01)==0x00){
goto exit_for;
}
}
exit_for:
if(cnt>=250){//擦除出错
}
else{
while(1){
rybystat=FLASHRYNBY;
if((rybystat&0x01)==0x01){//擦除完成
break;
}
else{
cnt++;
if(cnt==0xff)
;
}
}
}
}
void write_flash(union SFADD *p_add,unsigned char dat){
unsigned int flashspace;
union SFADD dwn_adres;
dwn_adres.l=p_add->l;
flashspace=dwn_adres.i[1];
flashspace &=0x3fff;
flashspace +=FLASH_SPACE_START;
dwn_adres.l <<=2;
WRITE_CMD;
FLASHADD=dwn_adres.c[1];
XBYTE[flashspace]=dat;
}
void read_flash(unsigned char hadd,unsigned int ladd,unsigned char len,unsigned char *buf){
unsigned char cnt;
unsigned int flashspace;
flashspace=0x4000;
flashspace +=ladd&0x3fff;
FLASHADD=hadd;
for(cnt=0;cnt<len;cnt++){
buf[cnt]=XBYTE[flashspace+cnt];
}
}
/******DS18b20温度传感器的操作*****/
unsigned char currSensorNo=0;
unsigned char ds18b20_init(){//初始花时序列
unsigned char i;
TMDAT=0;//要设置为低电平超过480微秒
delay_10us(48);//延时480微秒
TMDAT=1;//等待读芯片的输出.
delay_10us(6);//延时60微秒代表读时槽
if(TMDAT==0){//表明DS18B20存在
for(i=0;i<22;i++){
delay_10us(1);//ds18b20将保持线为低 60-240us
if(TMDAT){
return 2;
}
}
return 1;
}
else{
delay_10us(6);
return 0;
}
}
void tmwrite_1_slot(void){//写数据1时槽
TMDAT=0;
_nop_();_nop_();
_nop_();_nop_();//延时2微秒
TMDAT=1;
delay_10us(6);//延时60微秒
}
void tmwrite_0_slot(void){//写数据0时槽
TMDAT=0;
delay_10us(9);//延时90微秒
TMDAT=1;
_nop_();
}
/****从DS18B20中读一个字节的数据***/
unsigned char tmread_byte(void){
unsigned char i,dat=0;
for(i=1;i<=8;i++){
dat>>=1;
TMDAT=0;
_nop_();
TMDAT=1;
_nop_();_nop_();
_nop_();_nop_();
if(TMDAT){
dat |=0x80;
}
delay_10us(6);
}
return dat;
}
/****向ds18b20写一个字节的数据***/
void tmwrite_byte(unsigned char dat)
{
signed char i=0;
unsigned char j;
bit testb;
for(j=1;j<=8;j++){
testb=dat & 0x01;
dat = dat>>1;
if(testb){
tmwrite_1_slot();
}
else{
tmwrite_0_slot();
}
}
}
/*----------------------------------------------------
* 开始进行温度转换
*----------------------------------------------------*/
void tmstart(void){
ds18b20_init();
delay_10us(100);//延时1ms
tmwrite_byte(0xcc);//不匹配ROM 地址.
tmwrite_byte(0x44);//开始进行温度转换
}
/*----------------------------------------------------
* 读取转换后的温度,返回的值单位为温度,最高位为1表明为负的温度
*----------------------------------------------------*/
unsigned char tmrtemp_all(void){//读取温度值
unsigned char a,b;
unsigned char tm;//返回的温度值,单位为1度,最高位为1表明为负的温度
ds18b20_init();
delay_10us(100);//延时10毫秒
tmwrite_byte(0xcc);
tmwrite_byte(0xbe);//读温度命令
a = tmread_byte(); //读温度的低半字节
b = tmread_byte(); //读温度的高半字节
tm =(b << 4)&0xf0;
tm=tm|((a>>4)&0xf);//把数值转化以度为单位
delay_10us(1);
return tm ;
}
/**初始化LCD控制器**/
void Msm_init(void){//初始化msm6255
REG_INSTR=0X00;//选择模式控制寄存器
REG_DATA=0X0b;//光标关,显示开,4比特并行图形模式
REG_INSTR=0X01;//选择字符点数寄存器
REG_DATA=0X07;//一个字节的全部数据显示到屏幕上
REG_INSTR=0X02;//选择水平字符个数寄存器
REG_DATA=80;//每行显示81个字符,也就是81x8=648个点,这是根据AF1的时序设置的
REG_INSTR=0X03;//选择显示行数寄存器
REG_DATA=239;//选择行数为240行,因为是并行模式,所以总共为240x2=480行
REG_INSTR=0X05;//选择低端开始地址寄存器
REG_DATA=0; //设置显示存开始开始地址的低8位为0
REG_INSTR=0X06;//选择高端开始地址寄存器
REG_DATA=0; //设置显示存开始开始地址的高8位为0,这样显存开始地址就从0开始
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -