?? chip.c
字號(hào):
#include <./Atmel/at89x52.h>
#include <stdio.h>
#include "source.h"
#include <intrins.h>
#include <absacc.h>
//_nop_(); 在fosc=18.432MHZ時(shí),一個(gè)空語(yǔ)句是 0.65us
void delay_macnine_ncircle(unsigned char cnt){//11+6*cnt machin circle.
while(cnt--);
}
void delay_10us(unsigned char tus){//在晶振頻率為18.432MHZ時(shí)延時(shí)10微秒的函數(shù)
tus--;
while(tus--){
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
}
/*因?yàn)锳T24C4的最大速率為100k,所以需要延時(shí)*/
#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
/***以下的函數(shù)與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;//因故障接收方無(wú)ACK 超時(shí)值為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;
}
/***因?yàn)锳T24C64與SDA2000共用同樣的CPU管腳,其區(qū)分對(duì)不同芯片的操作是使用設(shè)備類型**/
/***來(lái)區(qū)分的,如EEPROM的地址為0xa,而SDA2000的設(shè)備地址為0x6*/
#define DEVICEAW 0Xa0
#define DEVICEAR 0Xa1
void AT24C64_wbytes(unsigned char *add,unsigned char len,unsigned char *buf){//向EEPROM中寫(xiě)數(shù)據(jù),最長(zhǎng)為32個(gè)字節(jié)
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);//因?yàn)镋EPROM在寫(xiě)下一個(gè)數(shù)據(jù)時(shí)要等待5ms.
delay_10us(100);
delay_10us(100);
delay_10us(100);
delay_10us(100);//延時(shí)了5ms.
}
void AT24C64_rbytes(unsigned char *add,unsigned char len,unsigned char *buf){//為讀EEPROM中的字節(jié)
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的內(nèi)容都初始化為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扇區(qū)
unsigned int n;
unsigned char cnt;
unsigned char temp;
unsigned char rybystat;
ERASE_CMD;
temp=sa;
if(sa<8){//每個(gè)扇區(qū)是8K字節(jié)
cnt=temp;
temp >>=1;
FLASHADD=temp;
if(cnt%2){
XBYTE[0X2000+FLASH_SPACE_START]=0X30;//擦除扇區(qū)命令.
}
else{
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇區(qū)命令.
}
}
else{//每個(gè)扇區(qū)是64k字節(jié)
cnt=temp-7;
temp=cnt <<2;
FLASHADD=temp;
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇區(qū)命令.
}
rybystat=FLASHRYNBY;
for(n=0;n<2000;n++){
if(rybystat&0x01==0x00){//開(kāi)始擦除.
goto my_exit;
}
rybystat=FLASHRYNBY;
}
my_exit:
while(1){
rybystat=FLASHRYNBY;
if(rybystat&0x01==0x01){
break;
}
}
if(cnt>=2000){
return 0;//不能開(kāi)始擦除
}
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 扇區(qū),每個(gè)扇區(qū)是8k字節(jié).
cnt=temp;
temp >>=1;
FLASHADD=temp;
if(cnt%2){
XBYTE[0X2000+FLASH_SPACE_START]=0X30;//擦除扇區(qū)命令.
}
else{
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇區(qū)命令.
}
}
else{//it is 64k pre sector.
cnt=temp-7;
temp=cnt <<2;
FLASHADD=temp;
XBYTE[FLASH_SPACE_START]=0X30;//擦除扇區(qū)命令.
}
}
for(cnt=0;cnt<250;cnt++){
rybystat=FLASHRYNBY;
if((rybystat&0x01)==0x00){
goto exit_for;
}
}
exit_for:
if(cnt>=250){//擦除出錯(cuò)
}
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(){//初始花時(shí)序列
unsigned char i;
TMDAT=0;//要設(shè)置為低電平超過(guò)480微秒
delay_10us(48);//延時(shí)480微秒
TMDAT=1;//等待讀芯片的輸出.
delay_10us(6);//延時(shí)60微秒代表讀時(shí)槽
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){//寫(xiě)數(shù)據(jù)1時(shí)槽
TMDAT=0;
_nop_();_nop_();
_nop_();_nop_();//延時(shí)2微秒
TMDAT=1;
delay_10us(6);//延時(shí)60微秒
}
void tmwrite_0_slot(void){//寫(xiě)數(shù)據(jù)0時(shí)槽
TMDAT=0;
delay_10us(9);//延時(shí)90微秒
TMDAT=1;
_nop_();
}
/****從DS18B20中讀一個(gè)字節(jié)的數(shù)據(jù)***/
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寫(xiě)一個(gè)字節(jié)的數(shù)據(jù)***/
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();
}
}
}
/*----------------------------------------------------
* 開(kāi)始進(jìn)行溫度轉(zhuǎn)換
*----------------------------------------------------*/
void tmstart(void){
ds18b20_init();
delay_10us(100);//延時(shí)1ms
tmwrite_byte(0xcc);//不匹配ROM 地址.
tmwrite_byte(0x44);//開(kāi)始進(jìn)行溫度轉(zhuǎn)換
}
/*----------------------------------------------------
* 讀取轉(zhuǎn)換后的溫度,返回的值單位為溫度,最高位為1表明為負(fù)的溫度
*----------------------------------------------------*/
unsigned char tmrtemp_all(void){//讀取溫度值
unsigned char a,b;
unsigned char tm;//返回的溫度值,單位為1度,最高位為1表明為負(fù)的溫度
ds18b20_init();
delay_10us(100);//延時(shí)10毫秒
tmwrite_byte(0xcc);
tmwrite_byte(0xbe);//讀溫度命令
a = tmread_byte(); //讀溫度的低半字節(jié)
b = tmread_byte(); //讀溫度的高半字節(jié)
tm =(b << 4)&0xf0;
tm=tm|((a>>4)&0xf);//把數(shù)值轉(zhuǎn)化以度為單位
delay_10us(1);
return tm ;
}
/**初始化LCD控制器**/
void Msm_init(void){//初始化msm6255
REG_INSTR=0X00;//選擇模式控制寄存器
REG_DATA=0X0b;//光標(biāo)關(guān),顯示開(kāi),4比特并行圖形模式
REG_INSTR=0X01;//選擇字符點(diǎn)數(shù)寄存器
REG_DATA=0X07;//一個(gè)字節(jié)的全部數(shù)據(jù)顯示到屏幕上
REG_INSTR=0X02;//選擇水平字符個(gè)數(shù)寄存器
REG_DATA=80;//每行顯示81個(gè)字符,也就是81x8=648個(gè)點(diǎn),這是根據(jù)AF1的時(shí)序設(shè)置的
REG_INSTR=0X03;//選擇顯示行數(shù)寄存器
REG_DATA=239;//選擇行數(shù)為240行,因?yàn)槭遣⑿心J剑钥偣矠?40x2=480行
REG_INSTR=0X05;//選擇低端開(kāi)始地址寄存器
REG_DATA=0; //設(shè)置顯示存開(kāi)始開(kāi)始地址的低8位為0
REG_INSTR=0X06;//選擇高端開(kāi)始地址寄存器
REG_DATA=0; //設(shè)置顯示存開(kāi)始開(kāi)始地址的高8位為0,這樣顯存開(kāi)始地址就從0開(kāi)始
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -