?? main.c
字號:
/**********************************************************************************************************
陜 西 ?? 電 子 有 限 公 司
Copyright (C), 2000-2008, LiFang Tech. Co., Ltd.
File name: // main.c
Author:zhuxz Version:v3.1 Date: 2008-8-29
Description: // 用于詳細說明此程序文件完成的主要功能,與其他模塊
// 或函數的接口,輸出值、取值范圍、含義及參數間的控
// 制、順序、獨立或依賴等關系
Others: // 其它內容的說明
集成開發環境:ICCAVR6.31A
主控芯片型號: ATMega16
晶振頻率: 外部 7.3728MHZ
波特率: 9600
**********************************************************************************************************/
#include <macros.h>
#include <string.h>
#include <stdlib.h>
#include <iom16v.h>
#include "main.h"
#include "initial.h"
#define TW_MR_SLA_ACK 0x40
#define TW_MR_SLA_NACK 0x48
#define TW_MR_DATA_ACK 0x50
#define TW_MR_DATA_NACK 0x58
#define TW_MTR_ARB_LOST 0x38
#define TW_MT_DATA_NACK 0x30
#define TW_MT_DATA_ACK 0x28
#define TW_MT_SLA_NACK 0x20
#define TW_MT_SLA_ACK 0x18
#define TW_REP_START 0x10
#define TW_START 0x08
#define RECVBUFFERLEN 14
//UART接收到PC緩沖區的長度
uchar UartRecvBuffer[RECVBUFFERLEN];
//UART接收緩沖區的索引
uchar UartRecvIndex = 0;
//接收PC傳來的UART完整一楨數據包標志
uchar gbRecvPCFrameCmd = 0;
//定義I2C總線的數據
//MCU I2C接收數據的緩存參數定義
uchar I2cReceiveDataIndex = 0;
uchar I2cReceiveDataLength= 0;
uchar I2cReceiveData[16];
//MCU I2C發送數據的緩存參數定義
uchar I2cSendData[16];
uchar I2cSendDataIndex = 0;
uchar I2cSendDataLength = 0;
//表明與I2C器件的通信狀態(成功:TRUE/失敗:FALSE)
uchar gbi2cSendCmdStatus = TRUE;
//MCU接收到I2C器件字節標志
uchar gbi2cRecvByteStatus = FALSE;
//MCU發送出字節標志
uchar gbi2cSendByteStatus = FALSE;
//Timer0溢出次數,用來控制刷卡時間
uint gTmr0OvrCount = 0;
//Timer2溢出次數,用來控制流水時間
uint gTmr2OvrCount = 0;
//鍵盤中斷標志
uchar cKeyRiseEvent = 0;
//FLASH地址操作的變量
uint gnCurrentFlashPage = 0; //當前操作的頁地址
uint gnCurrentBytesBlock = 0; //當前頁內的字節塊
uint gnHistoryFlashPage = 0; //歷史操作的頁地址
uint gnHistoryBytesBlock = 0; //歷史頁內的字節塊
void SoftDelay(void)
{
uint loop = 0;
for (loop = 0; loop <1000; loop++);
}
/*******************************************************************************
** 串口發送字節子程序
*******************************************************************************/
void Uart_Send(uchar senddata)
{
UDR = senddata;
while(!(UCSRA & (1<<UDRE))); //等待發送完
UCSRA |= 0x40; //清“發送完”標志位
}
/*******************************************************************************
** SPI發送字節子程序
*******************************************************************************/
void SPI_MasterTransmit(uchar cData)
{
/* 啟動數據傳輸 */
SPDR = cData;
/* 等待傳輸結束 */
while(!(SPSR & (1<<SPIF)));
}
//讀取某頁內字節地址的命令
uchar SPI_ReadPageCtx(uint page/*0~4095*/, uint byteAddr/*0~263*/)
{
uchar cData=0;
CLRBIT(PORTB,4);
SPI_MasterTransmit(0x52); //CMD, 1st
cData = 0x1F & ((char)(page>>7));
SPI_MasterTransmit(cData);//Page Addr High,2nd
cData = ((char)(page & 0x7F))<<1;
cData |= (char)((byteAddr & 0x1FF)>>8);
SPI_MasterTransmit(cData);//Page Addr low,3rd
cData = (char)(byteAddr & 0xFF);
SPI_MasterTransmit(cData);//byte Addr High,4th
//空命令,湊足剩余4字節
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
/* 等待傳輸結束 */
while(!(SPSR & (1<<SPIF)));
cData = SPDR;
SETBIT(PORTB,4);
return cData;
}
//寫入某頁內某字節地址的命令
void SPI_WritePageCtx(uint page/*0~4095*/, uint byteAddr/*0~263*/, uchar cByte)
{
uchar cData =0;
CLRBIT(PORTB,4);
//把數據寫入Buffer1
SPI_MasterTransmit(0x84); //CMD, 1st
SPI_MasterTransmit(0); //Not Care
cData |= (char)((byteAddr & 0x100)>>8);
SPI_MasterTransmit(cData);//Byte Addr High,3rd
cData = (char)(byteAddr & 0xFF);
SPI_MasterTransmit(cData);//Byte Addr High,4th
//傳輸字節
SPI_MasterTransmit(cByte);//Byte Data
SETBIT(PORTB,4);
}
//擦除FLASH芯片所有內容
char EraseFlashCtx(void)
{
uchar bResult = 1;
uchar cData = 0;
char page = 0;
CLRBIT(PORTB,4);
for (page =0; page<4096; page++)
{
SPI_MasterTransmit(0x58); //CMD, 1st
cData = 0x1F & ((char)(page>>7));
SPI_MasterTransmit(cData);//Page Addr High,2nd
cData = ((char)(page>>7))<<1;
SPI_MasterTransmit(cData);//Page Addr low,3rd
SPI_MasterTransmit(0); //not care
//讀取狀態寄存器
SPI_MasterTransmit(0x57);
/* 等待傳輸結束 */
while(!(SPSR & (1<<SPIF)));
cData = SPDR;
cData &= 0x40;
bResult &= (cData == 0);
}
SETBIT(PORTB,4);
return bResult;
}
//向FLASH中寫入已使用的總頁數和字節數,或下一個頁數和字節地址
void WriteContextInfo(uint curpage/*當前頁地址*/,
uchar curBlockIndex/*當前頁內字節塊的索引號*/)
{
//頁地址高字節和低字節(范圍:22..4095),20個字節的倍數(范圍:0..12)
SPI_WritePageCtx(0, 0, (uchar)(curpage>>8));
SPI_WritePageCtx(0, 1, (uchar)(curpage&0xFF));
SPI_WritePageCtx(0, 2, curBlockIndex);
}
//確認當前消費記錄寫操作成功,完成寫入和讀出的記錄錢數要相等。
//成功:1, 失敗:0。
char CommitPaidSuccess(uint curpage/*當前頁地址*/,
uchar curBlockIndex/*當前頁內字節塊的索引號*/, uchar *szBytes, uchar num)
{
char cByteNum = 0;
uchar CmpData[20];
//先寫入當前的記錄
for (cByteNum = 0; cByteNum<20; cByteNum++)
{
SPI_WritePageCtx(curpage, curBlockIndex*20+cByteNum, *szBytes++);
}
//再讀出當前消費記錄
for (cByteNum = 0; cByteNum<20; cByteNum++)
{
CmpData[cByteNum] = SPI_ReadPageCtx(curpage, curBlockIndex*20+cByteNum);
}
cByteNum = memcmp((void *)szBytes, (void *)CmpData, 20);
return cByteNum == 0;
}
//讀出前次消費記錄的待寫FLASH頁地址和頁內字節地址。
void GetHistoryPageAndBytesAddr(uint *oldpage, uint *oldByteAddr)
{
uchar cData = 0;
*oldpage = SPI_ReadPageCtx(0, 0);
cData = SPI_ReadPageCtx(0, 1);
*oldpage = *oldpage*256;
*oldpage += cData;
*oldByteAddr = SPI_ReadPageCtx(0, 2);
}
//計算出下次消費記錄的待寫FLASH頁地址和頁內字節地址。
//注意忽略每頁的后4個字節,只考慮使用前260個字節,每條記錄20個字節。
void CalcNextPageAndBytesAddr(uint oldpage, uint oldByteAddr, uint *newPage,
uint *newByteAddr)
{
*newByteAddr = oldByteAddr +1;
*newPage = oldpage;
if (*newByteAddr > 12) //換頁時
{
*newPage = oldpage + 1;
*newByteAddr = 0;
}
}
/*******************************************************************************
** 與I2C通信的子程序
*******************************************************************************/
void i2cSendByte(uchar data)
{
// 裝載數據到 TWDR
TWDR=data;
// 發送開始
TWCR = (TWCR&0x0F)|(1<<TWINT);
}
// 發送開始信號
void i2cSendStart(void)
{
TWCR = (TWCR&0x0F)|(1<<TWINT)|(1<<TWSTA);
}
// 發送停止信號
void i2cSendStop(void)
{
TWCR = (TWCR&0x0F)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
}
// 產生應答信號否
void i2cAckSignal(uchar ackFlag)
{
if( ackFlag )
TWCR = (TWCR&0x0F)|(1<<TWINT)|(1<<TWEA);
else
TWCR = (TWCR&0x0F)|(1<<TWINT);
}
//向I2C器件發送字符串
void I2C_SendInfo(uchar wsla, uchar suba, uchar *szBuff, uchar num)
{
I2cSendData[0] = wsla;
I2cSendData[1] = suba;
if (num > 0)
memcpy((void *)&I2cSendData[2], (void *)szBuff, num);
I2cSendDataLength = num+1;
I2cSendDataIndex = 0; //從從地址開始計算
//啟動I2C傳送
i2cSendStart();
}
//向I2C器件發送字符串
void I2C_RecvInfo(uchar wsla, uchar suba, uchar *szBuff, uchar num)
{
I2cSendData[0] = wsla;
I2cSendData[1] = suba;
//接收功能的變量
I2cReceiveDataLength = num;
I2cReceiveDataIndex = 0; //從0開始計算
//發送命令的變量
I2cSendDataIndex = 0; //專為子地址才有此代碼
I2cSendDataLength = 1;
gbi2cSendByteStatus = FALSE;
//先啟動I2C傳送寫從地址和子地址
i2cSendStart();
//再重啟I2C傳送,僅寫從地址
while(!gbi2cSendByteStatus); //等到已發送子地址后,可以接收數據
I2cSendData[0] = wsla+1;
i2cSendStart();
}
//向ZLG7290發送單個字節
void Zlg7290_SendChar(uchar SegNo, uchar cByte)
{
I2C_SendInfo(WriteZlg7290Addr, DPRAM0+SegNo, &cByte, 1);
}
//從ZLG7290讀取單個字節
uchar Zlg7290_ReadKey(void)
{
gbi2cRecvByteStatus = FALSE;
//需從鍵值寄存器讀取哪個鍵被按下
I2C_RecvInfo(WriteZlg7290Addr, 0x01, 0, 1);
//等到接收到回應
while (!gbi2cRecvByteStatus && I2cReceiveDataIndex < 1);
return I2cReceiveData[0];
}
//向M41T0發送多個字節,此處為時間(格式為:秒-分-小時-星期-日-月-年-控制字)
void M41T0_SendInfo(uchar *szData, uchar num)
{
I2C_SendInfo(WriteM41T0Addr, 0/*從秒開始*/, szData, num);
}
//從M41T0讀取多個字節,此處為時間(格式為:秒-分-小時-星期-日-月-年-控制字)
void M41T0_ReadInfo(uchar *szData, uchar num)
{
if (num != 8)
return;
gbi2cRecvByteStatus = FALSE;
//需從寄存器讀取時間
I2C_RecvInfo(WriteM41T0Addr, 0x0/*從秒開始*/, 0/*忽略*/, 8);
//等到接收到回應
while (!gbi2cRecvByteStatus && I2cReceiveDataIndex < 8);
memcpy((void *)szData, (void *)I2cReceiveData, num);
}
/**********************************************************************
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -