|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2005-4-20 00:35:25
|
显示全部楼层
先贴我的源代码,写得很丑大家不要笑我
// 镍镉电池组和镍氢电池组充电电路
// 使用ATMega8单片机
// 创建于2004/12/15
// 最后一次修改 2005/3/22
// 版权没有
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "ChargerAtmega8.h"
// UART value defInition
#define UART_TX_BUFFER_SIZE 16 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_MASK (UART_TX_BUFFER_SIZE - 1)
#define VOL_BUFFER_LEN 6
#define UART_RX_BUFFER_SIZE 8
#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE - 1)
#if (UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK)
#error RX buffer size is not a power of 2
#endif
// UART Data
volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
volatile unsigned char UART_TxHead;
volatile unsigned char UART_TxTail;
volatile unsigned char UART_RxTail;
// 系统状态
#define READY 1
#define CHARGING 2
#define CHECKING 3
#define FULL 4
volatile unsigned char gcState;
// 进程控制块
// PCB结构:0 程序指针,1 堆栈指针,2 进程状态字
// 状态字结构
// Bit1 & Bit0 00-Ready 01-Running 10-Waiting
// Bit3 & Bit2 优先级 00-1 01-2 10-3 11-4
// Bit11-Bit4 进程运行加权值
#define PROCESS_READY 0
#define PROCESS_RUNNING 1
#define PROCESS_WAITING 2
#define PROCESS_IDLE 3
struct ProcWord
{
unsigned int Rank:8; // 进程运行加权值
unsigned int Priority:2; // 优先级 00-1 01-2 10-3 11-4
unsigned int State:2; // 进程状态 00-Ready 01-Running 10-Waiting
};
struct ProcessControlBlock
{
unsigned int StackPoint;
unsigned char Message; // 每个进程的消息池
unsigned char WaitFor; // 等待的事件/资源编号 0-8
struct ProcWord ProcessWD;
};
// 进程标识
#define BAT_PROC 0
#define CUR_PROC 1
#define KEY_PROC 2
#define LCD_PROC 3
#define STA_PROC 4
#define PCB_NUMBER 5
volatile struct ProcessControlBlock PCB[PCB_NUMBER];
volatile unsigned char gcRunningProcessID;
// 事件标识
// 消息通知每个进程,gcSignal中相应的位代表该进程是否有消息
volatile unsigned char gcSignal;
// 每种进程的消息定义
// 给Battary_Monitor进程的
#define CHECK_BATTARY 1
#define EXT_ADC_ENDED 2
#define CURRENT_STOP 4
// 给Current_Monitor进程的
#define CHK_CUR_ENDED 1
#define CURRENT_ON 2
#define CURRENT_OFF 4
// 给Keyboard_Monitor进程的
#define CHK_KEY_ENDED 1
#define KEY_GET_READY 2
#define CHECK_KEY 4
// 给LCD_Monitor进程的
#define UPDATE_VOLTAGE 1
#define UPDATE_CURRENT 2
#define LCD_GET_READY 4
#define MOVE_CURSOR_LEFT 8
#define MOVE_CURSOR_RIGHT 16
#define ENTER_ITEM 32
#define LCD_FLASH 64
// 给State_Monitor进程的
#define LCD_READY 1
#define START_CHARGE 2
#define STOP_CHARGE 4
#define BAT_AD_ENDED 8
#define SOUND_FLASH 16
volatile unsigned int SYSTEM_STACK;
volatile unsigned int gnADC_CUR,gnADC_KEY;
volatile unsigned char gcMillisecond;
volatile unsigned char gcSecond,gcTenSecond,gcMinute;
volatile unsigned long glSumCurrent;
// 设定的充电电流值
volatile unsigned int gnCurrent;
// 设定的电池类型
volatile unsigned char gcTypeOfBattary;
// 电压队列
#define VOLT_ARRAY_LEN 18
volatile unsigned int gnVoltageArray[VOLT_ARRAY_LEN];
volatile unsigned int gnVoltage;
volatile unsigned char gcI = 0, gcJ = 0;
volatile unsigned char gacMenu[4][2]; // 菜单选择位置
int main(void)
{
// 响一下
sbi(DDRC, 2);sbi(PORTC, 2);
sbi(DDRB, 2);cbi(PORTB, 2);
gcSignal = 0; gcADC_In_Use = false;
gnVoltage = 0;
gcMillisecond = 0; gcSecond = 0; gcTenSecond = 0; gcMinute = 0;
UART_TxHead = 0; UART_TxTail = 0; UART_RxTail = 0;
// 初始化每个进程的状态为READY 消息为空
for(unsigned char i = 0; i < 5; i++)
{
PCB.ProcessWD.State = PROCESS_READY;
PCB.Message = 0;
}
// 设定各进程优先级
PCB[BAT_PROC].ProcessWD.Priority = 2;
PCB[CUR_PROC].ProcessWD.Priority = 1;
PCB[KEY_PROC].ProcessWD.Priority = 1;
PCB[LCD_PROC].ProcessWD.Priority = 0;
PCB[STA_PROC].ProcessWD.Priority = 0;
// 备份系统堆栈
SYSTEM_STACK = SP;
// 给各个进程分配独自堆栈空间 初始化堆栈
SP = SYSTEM_STACK - 128;
_SFR_MEM8(SP--) = (unsigned int)Battary_Monitor&0xFF;
_SFR_MEM8(SP--) = (unsigned int)Battary_Monitor>>8;
for(unsigned char i = 0; i <= 32; i++) asm volatile("push __zero_reg__"::);
PCB[BAT_PROC].StackPoint = SP;
SP = SYSTEM_STACK - 256;
_SFR_MEM8(SP--) = (unsigned int)Current_Monitor&0xFF;
_SFR_MEM8(SP--) = (unsigned int)Current_Monitor>>8;
for(unsigned char i = 0; i <= 32; i++) asm volatile("push __zero_reg__"::);
PCB[CUR_PROC].StackPoint = SP;
SP = SYSTEM_STACK - 384;
_SFR_MEM8(SP--) = (unsigned int)Keyboard_Monitor&0xFF;
_SFR_MEM8(SP--) = (unsigned int)Keyboard_Monitor>>8;
for(unsigned char i = 0; i <= 32; i++) asm volatile("push __zero_reg__"::);
PCB[KEY_PROC].StackPoint = SP;
SP = SYSTEM_STACK - 512;
_SFR_MEM8(SP--) = (unsigned int)LCD_Monitor&0xFF;
_SFR_MEM8(SP--) = (unsigned int)LCD_Monitor>>8;
for(unsigned char i = 0; i <= 32; i++) asm volatile("push __zero_reg__"::);
PCB[LCD_PROC].StackPoint = SP;
SP = SYSTEM_STACK;
PCB[STA_PROC].StackPoint = SP;
// 设波特率为9600
Init_UART(51);
// 初始化ADC
Init_Internal_ADC();
// 初始化TC2
Init_TC2();
// 设置看门狗
wdt_enable(WDTO_60MS);
// 允许睡眠模式
set_sleep_mode(0);
// TCCR0分频64
TCCR0 = 0x03;
// 开定时器0中断
sbi(TIMSK,TOIE0);
// 允许全局中断
sei();
TransmitByte('S');
gcRunningProcessID = STA_PROC;
State_Monitor();
}
void Scheduler(void)
{
wdt_reset();
for(unsigned char i = 0; i < PCB_NUMBER; i++)
{
if(bit_is_set(gcSignal, i) && PCB.Message&PCB.WaitFor
&& (PCB.ProcessWD.State == PROCESS_WAITING))
{
cbi(gcSignal, i);
PCB.WaitFor = 0;
PCB.ProcessWD.State = PROCESS_READY;
}
}
unsigned char cHighProcess = 0;
unsigned int nPriority,nPriority1;
if(PCB[0].ProcessWD.State == PROCESS_READY)
{
PCB[0].ProcessWD.Rank++;
nPriority = PCB[0].ProcessWD.Priority*4 + PCB[0].ProcessWD.Rank;
}
else
{
nPriority = 0;
cHighProcess = 1;
}
for(unsigned char i=1; i < PCB_NUMBER; i++)
{
if(PCB.ProcessWD.State == PROCESS_READY)
{
PCB.ProcessWD.Rank++;
nPriority1 = PCB.ProcessWD.Priority*4 + PCB.ProcessWD.Rank;
if(nPriority < nPriority1)
{
cHighProcess = i;
nPriority = nPriority1;
}
}
}
PCB[cHighProcess].ProcessWD.State = PROCESS_RUNNING;
PCB[cHighProcess].ProcessWD.Rank = 0;
gcRunningProcessID = cHighProcess;
}
void Idle(void)
{
PCB[gcRunningProcessID].ProcessWD.State = PROCESS_READY;
Wait();
}
void Wait_Message(unsigned char Message)
{
PCB[gcRunningProcessID].ProcessWD.State = PROCESS_WAITING;
PCB[gcRunningProcessID].WaitFor = Message;
Wait();
}
void Wait(void)
{
asm volatile("pop r17
\tpop r16"::);
asm volatile("push __zero_reg__
\tpush __tmp_reg__"::);
asm volatile("in __tmp_reg__,__SREG__"::);
asm volatile("push __tmp_reg__
\tclr __zero_reg__"::);
asm volatile("push r18
\tpush r19
\tpush r20"::);
asm volatile("push r21
\tpush r22
\tpush r23"::);
asm volatile("push r24
\tpush r25
\tpush r26"::);
asm volatile("push r27
\tpush r30
\tpush r31"::);
cbi(TIMSK,TOIE0);
asm volatile("push r2
\tpush r3
\tpush r4"::);
asm volatile("push r5
\tpush r6
\tpush r7"::);
asm volatile("push r8
\tpush r9
\tpush r10"::);
asm volatile("push r11
\tpush r12
\tpush r13"::);
asm volatile("push r14
\tpush r15
\tpush r16"::);
asm volatile("push r17
\tpush r28
\tpush r29"::);
PCB[gcRunningProcessID].StackPoint = SP;
Scheduler();
SP = PCB[gcRunningProcessID].StackPoint;
asm volatile("pop r29
\tpop r28
\tpop r17"::);
asm volatile("pop r16
\tpop r15
\tpop r14"::);
asm volatile("pop r13
\tpop r12
\tpop r11"::);
asm volatile("pop r10
\tpop r9
\tpop r8"::);
asm volatile("pop r7
\tpop r6
\tpop r5"::);
asm volatile("pop r4
\tpop r3
\tpop r2"::);
sbi(TIMSK,TOIE0);
asm volatile("pop r31
\tpop r30
\tpop r27"::);
asm volatile("pop r26
\tpop r25
\tpop r24"::);
asm volatile("pop r23
\tpop r22
\tpop r21"::);
asm volatile("pop r20
\tpop r19
\tpop r18"::);
asm volatile("pop __tmp_reg__
\tout __SREG__,__tmp_reg__"::);
asm volatile("pop __tmp_reg__
\tpop __zero_reg__"::);
asm volatile("reti"::);
}
void Send_Message(unsigned char ProcessID, unsigned char Message)
{
sbi(gcSignal, ProcessID);
PCB[ProcessID].Message |= Message;
}
void Battary_Monitor(void)
{
while(1)
{
UDR = 0x37;
Wait_Message(CHECK_BATTARY);
PCB[BAT_PROC].Message = 0;
if(gcState == CHARGING)
{
UDR = 'a';
Send_Message(CUR_PROC, CURRENT_OFF);
Wait_Message(CURRENT_STOP);
}
UDR = 'A';
unsigned int nVoltageArray[6];
for(unsigned char i = 0; i < 6; i++)
{
Init_TC1(ICP);
Start_External_ADC();
Wait_Message(EXT_ADC_ENDED);
PCB[BAT_PROC].Message = 0;
Stop_External_ADC();
nVoltageArray = gnVoltage;
}
UDR = 0x30+gcState;
if(gcState == CHECKING) Send_Message(CUR_PROC, CURRENT_ON);
gnVoltage = Average(nVoltageArray, 6);
Send_Message(LCD_PROC, UPDATE_VOLTAGE);
Send_Message(STA_PROC, BAT_AD_ENDED);
}
}
void Current_Monitor(void)
{
unsigned int nSumCount = 0, nPWM_Duty = 0;
unsigned long lSumCurrent = 0;
glSumCurrent = 0;
while(1)
{
if(gcState == CHARGING)
{
if(PCB[CUR_PROC].Message&CURRENT_OFF)
{
gcState = CHECKING;
PCB[CUR_PROC].Message &= ~CURRENT_OFF;
Start_TC1(CLKSTOP);
cbi(PORTB,1);
cbi(DDRB,1);
Send_Message(BAT_PROC, CURRENT_STOP);
}
else
{
// 启动电流检查
while(!Run_Internal_ADC(CURRENT)) Idle();
// 等AD转换结束
Wait_Message(CHK_CUR_ENDED);
PCB[CUR_PROC].Message &= ~CHK_CUR_ENDED;
// 调整电流
if(gnADC_CUR < gnCurrent) nPWM_Duty++;
else if(gnADC_CUR > gnCurrent) nPWM_Duty--;
OCR1A = nPWM_Duty;
// 求测得的电流平均值并显示 每512次采样求一次
lSumCurrent += gnADC_CUR;
if(++nSumCount >= 512)
{
nSumCount = 0;
Send_Message(LCD_PROC, UPDATE_CURRENT);
glSumCurrent = lSumCurrent;
lSumCurrent = 0;
}
}
}
else if(gcState == CHECKING)
{
if(PCB[CUR_PROC].Message&CURRENT_ON)
{
gcState = CHARGING;
PCB[CUR_PROC].Message &= ~CURRENT_ON;
Init_TC1(PWM);
OCR1A = nPWM_Duty;
Start_TC1(CLKIO);
}
}
else
{
cbi(PORTB,1);
cbi(DDRB,1);
Idle();
}
}
}
void Keyboard_Monitor(void)
{
unsigned char cKey_Count = 0;
// 初始化菜单
// 菜单
gacMenu[0][0] = 2;
gacMenu[1][0] = 29;
gacMenu[2][0] = 7;
gacMenu[3][0] = 1;
gacMenu[0][1] = 0;
gacMenu[1][1] = 0;
gacMenu[2][1] = 0;
gacMenu[3][1] = 0;
Wait_Message(KEY_GET_READY);
PCB[KEY_PROC].Message = 0;
while(1)
{
Wait_Message(CHECK_KEY);
PCB[KEY_PROC].Message = 0;
// 启动键盘扫描
while(!Run_Internal_ADC(KEY_BOARD)) Idle();
// 等AD转换结束
Wait_Message(CHK_KEY_ENDED);
PCB[KEY_PROC].Message = 0;
unsigned int nKey = gnADC_KEY;
if(gnADC_KEY < 800)
{
// 消抖晃
if(++cKey_Count == 10)
{
if(nKey < 100)
{
if(gcJ == 0)
{
if(gcI > 0) gcI--;
else gcI = 3;
}
else
{
if(gacMenu[gcI][gcJ] > 0) gacMenu[gcI][gcJ]--;
else gacMenu[gcI][gcJ] = gacMenu[gcI][0];
}
if(gcState == READY) Send_Message(LCD_PROC, MOVE_CURSOR_LEFT);
UDR = '-';
}
else if(nKey > 300 && nKey < 360)
{
if(gcJ == 0) gcJ = 1;
else gcJ = 0;
if(gcI == 3)
{
if(gcState == READY)
{
UDR = 's';
gnCurrent = (gacMenu[1][1] + 1)*25;
gcTypeOfBattary = gacMenu[0][1];
Send_Message(STA_PROC, START_CHARGE);
Clear_Screen(LOW);
}
else if(gcState == CHARGING || gcState == CHECKING)
{
UDR = 't';
Send_Message(STA_PROC, STOP_CHARGE);
}
}
Send_Message(LCD_PROC, ENTER_ITEM);
UDR = 'E';
}
else if(nKey > 616 && nKey < 716)
{
if(gcJ == 0)
{
if(gcI < 3) gcI++;
else gcI = 0;
}
else
{
if(gacMenu[gcI][gcJ] < gacMenu[gcI][0]) gacMenu[gcI][gcJ]++;
else gacMenu[gcI][gcJ] = 0;
}
if(gcState == READY) Send_Message(LCD_PROC, MOVE_CURSOR_RIGHT);
UDR = '+';
}
}
}
else cKey_Count = 0;
}
}
void LCD_Monitor(void)
{
// 初始化液晶屏
Init_Screen();
Send_Message(STA_PROC, LCD_READY); // 通知State_Monitor LCD初始化完成
Wait_Message(LCD_GET_READY); // 等待State_Monitor回应
PCB[LCD_PROC].Message = 0;
Clear_Screen(ALL); // 清屏
Display_Battary_Type(gacMenu[0][1], NORM);
Display_Battary_Cap(gacMenu[1][1], NORM);
Display_Battary_Voltage(gacMenu[2][1], NORM);
Display_Start_Stop(1);
Display_Arrow(gcI);
while(1)
{
if(PCB[LCD_PROC].Message & UPDATE_VOLTAGE)
{
PCB[LCD_PROC].Message &= ~UPDATE_VOLTAGE;
Voltage_To_Screen(gnVoltage);
}
if(PCB[LCD_PROC].Message & UPDATE_CURRENT)
{
PCB[LCD_PROC].Message &= ~UPDATE_CURRENT;
Current_To_Screen((glSumCurrent>>9)*2);
}
if(PCB[LCD_PROC].Message & MOVE_CURSOR_LEFT)
{
UDR = 'L';
PCB[LCD_PROC].Message &= ~MOVE_CURSOR_LEFT;
if(gcJ == 1)
{
if(gcI == 0) Display_Battary_Type(gacMenu[gcI][1], REVERSE);
else if(gcI == 1) Display_Battary_Cap(gacMenu[gcI][1], REVERSE);
else if(gcI == 2) Display_Battary_Voltage(gacMenu[gcI][1], REVERSE);
}
else Display_Arrow(gcI);
}
if(PCB[LCD_PROC].Message & MOVE_CURSOR_RIGHT)
{
UDR = 'R';
PCB[LCD_PROC].Message &= ~MOVE_CURSOR_RIGHT;
if(gcJ == 1)
{
if(gcI == 0) Display_Battary_Type(gacMenu[gcI][1], REVERSE);
else if(gcI == 1) Display_Battary_Cap(gacMenu[gcI][1], REVERSE);
else if(gcI == 2) Display_Battary_Voltage(gacMenu[gcI][1], REVERSE);
}
else Display_Arrow(gcI);
}
if(PCB[LCD_PROC].Message & ENTER_ITEM)
{
PCB[LCD_PROC].Message &= ~ENTER_ITEM;
if(gcJ == 1)
{
if(gcI == 0) Display_Battary_Type(gacMenu[gcI][1], REVERSE);
else if(gcI == 1) Display_Battary_Cap(gacMenu[gcI][1], REVERSE);
else if(gcI == 2) Display_Battary_Voltage(gacMenu[gcI][1], REVERSE);
}
else
{
if(gcI == 0) Display_Battary_Type(gacMenu[gcI][1], NORM);
else if(gcI == 1) Display_Battary_Cap(gacMenu[gcI][1], NORM);
else if(gcI == 2) Display_Battary_Voltage(gacMenu[gcI][1], NORM);
}
}
if(PCB[LCD_PROC].Message & LCD_FLASH)
{
PCB[LCD_PROC].Message &= ~LCD_FLASH;
}
}
}
void State_Monitor(void)
{
unsigned char cTime = 0;
Wait_Message(LCD_READY);
PCB[STA_PROC].Message = 0;
Beep(OFF);
gcState = READY;
Send_Message(LCD_PROC, LCD_GET_READY); // 启动LCD进程
Send_Message(KEY_PROC, KEY_GET_READY); // 启动键盘监控进程
while(1)
{
if(gcState == READY)
{
Wait_Message(START_CHARGE);
// 是否收到开始充电的信号
if(PCB[STA_PROC].Message & START_CHARGE)
{
PCB[STA_PROC].Message &= ~START_CHARGE;
gcState = CHARGING;
Send_Message(BAT_PROC, CHECK_BATTARY);
}
}
if(gcState == CHARGING || gcState == CHECKING)
{
Wait_Message(STOP_CHARGE|BAT_AD_ENDED);
// 是否收到停止充电的信号
if(PCB[STA_PROC].Message & STOP_CHARGE)
{
PCB[STA_PROC].Message &= ~STOP_CHARGE;
gcState = READY; // 暂停充电 置充电器为READY状态
}
if(PCB[STA_PROC].Message & BAT_AD_ENDED)
{
PCB[STA_PROC].Message &= ~BAT_AD_ENDED;
// 判断电池是否充满
for(unsigned char i = VOLT_ARRAY_LEN-1; i > 0; i--)
gnVoltageArray = gnVoltageArray[i-1]; // 电压值队列顺序移位
gnVoltageArray[0] = gnVoltage;
if(Battary_Full(gnVoltageArray, gcTypeOfBattary))
{
gcState = FULL;
}
}
}
if(gcState == FULL)
{
Wait_Message(SOUND_FLASH);
PCB[STA_PROC].Message &= ~SOUND_FLASH;
Display_Full();
if(++cTime == 8)
{
Beep(ON);
cTime = 0;
}
else Beep(OFF);
}
}
}
INTERRUPT(SIG_OVERFLOW0)
{
asm volatile("push r2
\tpush r3
\tpush r4"::);
asm volatile("push r5
\tpush r6
\tpush r7"::);
asm volatile("push r8
\tpush r9
\tpush r10"::);
asm volatile("push r11
\tpush r12
\tpush r13"::);
asm volatile("push r14
\tpush r15
\tpush r16"::);
asm volatile("push r17
\tpush r28
\tpush r29"::);
PCB[gcRunningProcessID].ProcessWD.State = PROCESS_READY;
if(++gcMillisecond == 255)
{
UDR = 0x30+gcState;
gcMillisecond = 0;
if(gcState == READY) Send_Message(LCD_PROC, LCD_FLASH);
else if(gcState == FULL) Send_Message(STA_PROC, SOUND_FLASH);
if(++gcSecond >= 20)
{
if(gcState == CHARGING)
{
if(gcTenSecond & 0x01) Send_Message(BAT_PROC, CHECK_BATTARY);
}
UDR = 'M';
gcSecond = 0;
if(++gcTenSecond >= 6)
{
gcTenSecond = 0;
gcMinute++;
}
}
}
Send_Message(KEY_PROC, CHECK_KEY);
PCB[gcRunningProcessID].StackPoint = SP;
Scheduler();
SP = PCB[gcRunningProcessID].StackPoint;
asm volatile("pop r29
\tpop r28
\tpop r17"::);
asm volatile("pop r16
\tpop r15
\tpop r14"::);
asm volatile("pop r13
\tpop r12
\tpop r11"::);
asm volatile("pop r10
\tpop r9
\tpop r8"::);
asm volatile("pop r7
\tpop r6
\tpop r5"::);
asm volatile("pop r4
\tpop r3
\tpop r2"::);
}
INTERRUPT(SIG_INPUT_CAPTURE1)
{
unsigned int temp = 0;
temp = ICR1L;
temp |= ICR1H << 8;
if(bit_is_set(TCCR1B,ICES1))
{
cbi(TCCR1B, ICES1);
gnVoltage = temp;
}
else
{
gnVoltage = temp - gnVoltage;
gnVoltage -= 0x2711;
Send_Message(BAT_PROC, EXT_ADC_ENDED);
}
}
INTERRUPT(SIG_ADC)
{
unsigned int nADC = ADCL;
nADC |= ADCH << 8;
unsigned char temp = ADMUX;
temp &= 0x0F;
if(temp == CURRENT)
{
gnADC_CUR = nADC;
Send_Message(CUR_PROC, CHK_CUR_ENDED);
}
else if(temp == KEY_BOARD)
{
gnADC_KEY = nADC;
Send_Message(KEY_PROC, CHK_KEY_ENDED);
}
ADMUX &= 0xF0;
gcADC_In_Use = false;
}
SIGNAL(SIG_UART_DATA)
{
/* check if all data is transmitted */
if(UART_TxHead != UART_TxTail )
{
/* calculate buffer index */
UART_TxTail = (UART_TxTail + 1 ) & UART_TX_BUFFER_MASK;
UDR = UART_TxBuf[UART_TxTail]; /* start transmition */
}
else cbi(UCSRB,UDRIE); // disable UDR interrupt
}
SIGNAL(SIG_UART_RECV)
{
unsigned char cReceivedByte;
cReceivedByte = UDR;
// TransmitByte(cReceivedByte); // 回显字符
UART_RxBuf[UART_RxTail] = cReceivedByte;
UART_RxTail = (UART_RxTail + 1) & UART_TX_BUFFER_MASK;
} |
|