这是tsg9456原作者在实际应用中的源程序,希望能帮到大家
运行代码 复制代码
#include "synth.h"
//------------------------------------------------------------------------------
bool CommState; // 通讯状态
bool Request; // 允许接收
bool Response; // 允许发送
bool EnCommWrite; // 允许通讯写
uchar UDRBuf; // 通讯接收寄存器缓存
uchar CommIndex; // 通讯索引
uchar CrcLow; // CRC低字节
uchar CrcHigh; // CRC高字节
uchar Interval; // 3.5字符时间间隔
uchar CommWrEntry; // 通讯写入口
uchar CommBuf[BUF_SIZE]; // 通讯缓冲区
uint StartAddr; // 起始地址
uint RegNum; // 寄存器数量
int bAudBuf; // 通讯波特率缓存
int FormBuf; // 通讯数据格式缓存
extern const StrKeybd Keybd[];
//------------------------------------------------------------------------------
void ResetInterval(void) // 重置3.5字符时间间隔
{
switch(bAudBuf)
{
case 0: Interval = (uchar)(1000/( 1200/11.0)*3.5/TBASE); break;
case 1: Interval = (uchar)(1000/( 2400/11.0)*3.5/TBASE); break;
case 2: Interval = (uchar)(1000/( 4800/11.0)*3.5/TBASE); break;
default: Interval = (uchar)(1000/( 9600/11.0)*3.5/TBASE); break;
case 4: Interval = (uchar)(1000/(19200/11.0)*3.5/TBASE); break;
}
}
//******************************************************************************
void OpenComm(void) // 打开或关闭通讯
{
ResetInterval();
UCA0CTL1 |= (UCSSEL_2 + UCRXEIE);
switch(FormBuf)
{
default: UCA0CTL0 = UCSPB; break; // N-2
case 1: UCA0CTL0 = UCPEN; break; // O-1
case 2: UCA0CTL0 = UCPEN + UCPAR; break; // E-1
case 3: UCA0CTL0 = 0; break; // N-1
}
switch(bAudBuf)
{
case 0: UCA0BR1 = (uint)(BRCLK/1200) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/1200));
UCA0MCTL = (uint)((BRCLK/1200-(uint)(BRCLK/1200))*8)<<1;
break;
case 1: UCA0BR1 = (uint)(BRCLK/2400) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/2400));
UCA0MCTL = (uint)((BRCLK/2400-(uint)(BRCLK/2400))*8)<<1;
break;
case 2: UCA0BR1 = (uint)(BRCLK/4800) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/4800));
UCA0MCTL = (uint)((BRCLK/4800-(uint)(BRCLK/4800))*8)<<1;
break;
default: UCA0BR1 = (uint)(BRCLK/9600) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/9600));
UCA0MCTL = (uint)((BRCLK/9600-(uint)(BRCLK/9600))*8)<<1;
break;
case 4: UCA0BR1 = (uint)(BRCLK/19200) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/19200));
UCA0MCTL = (uint)((BRCLK/19200-(uint)(BRCLK/19200))*8)<<1;
break;
}
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0RXIE;
}
//******************************************************************************
void Communication(void) // 通讯
{
if((SMM.out1 == COMM) || (SMM.out2 == COMM) || (SMM.out3 == COMM))
{
if((bAudBuf != SMM.bAud) || (FormBuf != SMM.ForM) || (!CommState))
{
bAudBuf = SMM.bAud;
FormBuf = SMM.ForM;
UCA0CTL1 = UCSWRST;
OpenComm();
CommState = true;
}
}
else
{
UCA0CTL1 = UCSWRST;
CommState = false;
}
}
//******************************************************************************
void SingleCRC(uchar data) // 计算单字节CRC校验码
{
uchar c = CrcLow ^ data;
CrcLow = TabCRC[c] ^ CrcHigh;
CrcHigh = TabCRC[c + 0x100];
}
//******************************************************************************
__monitor void SilentInterval(void) // 检测通讯3.5字符时间间隔
{
if(CommState)
{
if(Interval == 0)
{
ResetInterval();
CrcLow = 0xFF;
CrcHigh = 0xFF;
CommIndex = 0;
if(Response)
{
Response = false;
IE2 |= UCA0TXIE;
}
else
{
IE2 &= ~UCA0TXIE;
Request = true;
}
}
else
--Interval;
}
}
//******************************************************************************
bool CheckDataValid(void) // 检测写入数据的有效性
{
uchar c, index = StartAddr + OFFSET;
for(c = 0; c < RegNum; ++c, ++index)
{
uchar buf = c * 2;
int data = ((int)CommBuf[7 + buf] << 8) | CommBuf[8 + buf];
if((data < Keybd[index].LowerLimit) || (data > Keybd[index].HigherLimit))
return(false);
}
return(true);
}
//******************************************************************************
void GetDataToMenu(void) // 更新参数值
{
uchar c, *ta = &SB[(StartAddr + OFFSET) * 2], *src = &CommBuf[8];
for(c = RegNum; c; --c)
{ // 低字节
*ta = *src;
ta += 2; src += 2;
}
ta = &SB[(StartAddr + OFFSET) * 2 + 1], src = &CommBuf[7];
for(c = RegNum; c; --c)
{ // 高字节
*ta = *src;
ta += 2; src += 2;
}
}
//******************************************************************************
void GetDataToBuff(void) // 取参数值
{
uchar c, *ta = &CommBuf[4], *src = &SB[(StartAddr + OFFSET) * 2];
for(c = RegNum; c; --c)
{ // 低字节
*ta = *src;
ta += 2; src += 2;
}
ta = &CommBuf[3], src = &SB[(StartAddr + OFFSET) * 2 + 1];
for(c = RegNum; c; --c)
{ // 高字节
*ta = *src;
ta += 2; src += 2;
}
}
//******************************************************************************
void ManageWrite(void) // 写指令
{
uchar c = REGNUM * 2 + 7; // 指向CRCL
if(CommIndex < c)
{
SingleCRC(UDRBuf);
CommBuf[CommIndex++] = UDRBuf;
}
else if(CommIndex == c)
{
if(CrcLow == UDRBuf)
{
StartAddr = STARTADDR;
RegNum = REGNUM;
++CommIndex;
}
else
Request = false;
}
else
{
Request = false;
if(CrcHigh == UDRBuf)
{
if((RegNum >= 1) && (RegNum <= 0x7B) && (CommBuf[6] == (RegNum * 2)))
{
if((StartAddr + RegNum) <= COMM_WL_WR)
{
if(!CheckDataValid())
{
CMD |= 0x80; CommBuf[2] = ERR_DATA; // 非法数据
}
else
{
GetDataToMenu();
if(StartAddr < (COMM_WL_WR - 2))
{
switch(StartAddr+RegNum)
{
case COMM_WL_WR : RegNum -= 2; break;
case (COMM_WL_WR-1): RegNum -= 1; break;
default : break;
}
CommWrEntry = ENTRY;
EnCommWrite = true;
}
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_ADDR; // 非法地址
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_NUM; // 非法数量
}
Response = true;
}
}
}
//******************************************************************************
void ManageRead(void) // 读指令
{
if(CommIndex == 6)
{
if(CrcLow == UDRBuf)
{
StartAddr = STARTADDR;
RegNum = REGNUM;
CommBuf[2] = RegNum * 2;
++CommIndex;
}
else
Request = false;
}
else
{
Request = false;
if(CrcHigh == UDRBuf)
{
if((RegNum >= 1) && (RegNum <= 0x7D))
{
if((StartAddr + RegNum) <= COMM_WL_RD)
GetDataToBuff();
else
{
CMD |= 0x80; CommBuf[2] = ERR_ADDR; // 非法地址
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_NUM; // 非法数量
}
Response = true;
}
}
}
//******************************************************************************
#pragma vector = USCIAB0TX_VECTOR
__interrupt void UART_transmit(void) // 通讯发送
{
uchar c;
TACCTL0 &= ~CCIE;
IE2 &= ~UCA0TXIE;
__enable_interrupt();
ResetInterval();
if(CMD == READ) // 读指令
c = CommBuf[2] + 3; // 指向CRCL
else if(CMD == WRITE) // 写指令
c = 6;
else // 错误的指令
c = 3;
if(CommIndex <= (c + 1))
{
if(CommIndex < c)
{
c = CommBuf[CommIndex];
SingleCRC(c);
UCA0TXBUF = c;
}
else if(CommIndex == c)
UCA0TXBUF = CrcLow;
else
UCA0TXBUF = CrcHigh;
++CommIndex;
__disable_interrupt();
IE2 |= UCA0TXIE;
TACCTL0 |= CCIE;
}
else
{
__disable_interrupt();
TACCTL0 |= CCIE;
}
}
//******************************************************************************
#pragma vector = USCIAB0RX_VECTOR
__interrupt void UART_receive(void) // 通讯接收
{
UDRBuf = UCA0RXBUF;
TACCTL0 &= ~CCIE;
IE2 &= ~UCA0RXIE;
__enable_interrupt();
ResetInterval();
if(Request)
{
switch(CommIndex)
{
case 0: if(UDRBuf != SMM.Addr)
{
Request = false;
break;
}
case 1:
case 2:
case 3:
case 4:
case 5: SingleCRC(UDRBuf);
CommBuf[CommIndex++] = UDRBuf;
break;
default: if(CMD == READ) // 读指令
ManageRead();
else if(CMD == WRITE) // 写指令
ManageWrite();
else // 非法指令
{
Request = false;
CMD |= 0x80; CommBuf[2] = ERR_CMD;
Response = true;
}
break;
}
}
__disable_interrupt();
IE2 |= UCA0RXIE;
TACCTL0 |= CCIE;
}
欢迎发贴分享设计心得、开源DIY...
tsg9456
2009-09-24 13:36:27 引用 只看此人 评帖
2楼
头像级别
关注Ta给tsg9456发消息
MCP33:微控3.3V/1uA超低功耗LDO现货供应
说明一下:
仪表有一个2ms的系统时钟,每2ms将3.5字符时间-1,如果字符时间已减为0,将通讯资源重置,允许新的接收或发送开始,通讯写只是建立了写使能标志和缓存了写操作用到的资源,具体的应用是检测到写入标志就执行写入(可以在主程序或系统时钟中断中写入),删除部分冗余的指令即可直接应用于实际的系统
宏定义如下:
//------------------------------------------------------------------------------
#define ERR_CMD 0x01 // 非法指令
#define ERR_ADDR 0x02 // 非法地址
#define ERR_NUM 0x03 // 非法数量
#define ERR_DATA 0x04 // 非法数据
#define READ 0x03 // 读
#define WRITE 0x10 // 写
#define CMD CommBuf[1] // 指令
#define STARTADDR (((uint)CommBuf[2]<<8)|CommBuf[3]) // 起始地址
#define REGNUM (((uint)CommBuf[4]<<8)|CommBuf[5]) // 寄存器数量
//------------------------------------------------------------------------------
const uchar TabCRC[] =
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
#endif
typedef struct
{
uchar StateTable[4][2]; // 状态表
uchar code[4]; // 参数代号
uchar address; // 参数地址
uchar decimal; // 小数点位置
int LowerLimit; // 下限
int HigherLimit; // 上限
int initial; // 初值
const uchar *pointer; // 参数值转换为字符的指针(用于参数值显示为字符)
}StrKeybd;
const StrKeybd Keybd[] =
{
内容根据StrKeybd结构填入即可。
};
//------------------------------------------------------------------------------
typedef struct
{
}StrMenu;
typedef struct
{
}StrParm;
//------------------------------------------------------------------------------
typedef struct
{
StrMenu Menu;
StrParm Parm;
}StrSynth;
typedef union
{
uchar Byte[sizeof(StrSynth)];
uint Word[sizeof(StrSynth)/2];
StrSynth Member;
}UniSynth;
UniSynth Synth;
运行代码 复制代码
#define SB Synth.Byte
#define SW Synth.Word
#define SMM Synth.Member.Menu
#define SMP Synth.Member.Parm
#endif
|