|
发表于 2009-5-30 22:00:57
|
显示全部楼层
//仿三菱PLC与触摸屏的通讯程序 现在还只能用D和M,其他单元应该很好扩展
//希望对大家做通讯有帮助!由于水平有限,有错误的地方请大家帮忙纠正一下.
#include <stm32f10x_lib.h> // STM32F10x Library Definitions
//#include <stdio.h>
#include "STM32_Init.h" // STM32 Initialization
uint8 comrx[256]; // UART0数据接收缓冲区
uint8 comtx[256]; // UATT0数据发送缓冲区
//uint8 rcv_new; // 接收新数据标志
uint16 v_variable[256]; //触摸屏通讯控制的D字节单元
uint8 bit_data[64]; //触摸屏通讯控制的B位单元
uint8 rxcount=2;//接收计数器
uint8 secount=1;//发送计数器
uint8 rxend;//和校验
uint8 rxflish=0,endbit=0;//
uint8 txreg;//发送位数计数器
void clrbit(void);
void setbit(void);
void writebyte(void);
int read16bit(uchar *reip);
void readbyte(void);
void readbit(void);
uchar sumsdd(uchar su1);
uchar charjiema(uchar *chip);
uchar charaiss(uchar cam);
void coding(void);
void senderr(void);
void SendByte(uint8 data);
void SendString(uchar *sendip);
void SendStringx(uint8 const *data);
void timex(int tims);
/****************************************************************************
* 名称:addchack()
* 功能:和校验。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
adcount 和校验数据的个数
* 出口参数:无
****************************************************************************/
uchar addchack(uchar adcount)//和校验
{
uchar sadd,si;
sadd=0;
for(si=0x00;si<adcount-1;si++)
{
sadd+=comrx[si];
}
si=charjiema(&comrx[adcount-1]);//转换ASIIC的和值为十六进制
if(sadd==si)
{return(1);}
else
{return(0);}
}
/****************************************************************************
* 名称:senderr()
* 功能:发送错误信号。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void senderr(void)//发送错误
{
SendByte(0x15);
}
/****************************************************************************
* 名称:coding()
* 功能:接收解码。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
rxflish 开始解码标志 (全局变量)
rxcount 接收数据的个数(全局变量)
* 出口参数:无
****************************************************************************/
void coding(void)//接收解码
{
if(rxflish)//开始解码
{
rxflish=0;
if(addchack(rxcount-1)==0x01)//接收和校验正确
{
switch (comrx[0] )
{
case 0x30://读处理
if(comrx[1]==0x30)
{
readbit();//读位
}
else
{
readbyte();//读字节
}
break;
case 0x31://写处理
writebyte();//写字节
break;
case 0x37://置位
setbit();
break;
case 0x38://清位
clrbit();
break;
}
}
else
{
senderr();//发送错误
}
}
}
/****************************************************************************
* 名称:charaiss()
* 功能:ASIIC码转十六进制
* 入口参数:
cam 要转换数据
* 出口参数:
cam 转换后的数据
****************************************************************************/
uchar charaiss(uchar cam)//ASIIC码转十六进制
{
if(cam<0x40)
{
cam=cam-0x30;
}
else
{
cam=cam-0x37;
}
return(cam);
}
/****************************************************************************
* 名称:charjiema()
* 功能:解码二位ASIIC为一位十六进制。
* 入口参数:
chip 要转换数据的指针
* 出口参数:
ch_a 转换后的数据
****************************************************************************/
uchar charjiema(uchar *chip)//解码二位ASIIC为一位十六进制
{
uchar ch_a=0,ch_b=0;
ch_a=charaiss(*chip);
ch_a=ch_a<<4;
chip++;
ch_b=charaiss(*chip);
ch_a=ch_a|ch_b;
return(ch_a);
}
/****************************************************************************
* 名称:sumsdd()
* 功能:求和校验值。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
su1 要求和数据的个数
* 出口参数:
su1 要发送数据的个数
****************************************************************************/
uchar sumsdd(uchar su1)//求和校验值
{
uchar si,ssd;
ssd=0;
for(si=1;si<=su1;si++)//求和
{
ssd+=comtx[si];
}
si=ssd>>4;
if(si>0x09)//转成ASIIC码
{si=si+0x37;}
else
{si=si+0x30;}
su1++;
comtx[su1]=si;
si=ssd&0x0f;
if(si>0x09)
{si=si+0x37;}
else
{si=si+0x30;}
su1++;
comtx[su1]=si;
return(su1+1);
}
/****************************************************************************
* 名称:readbit()
* 功能:读位操作。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
bit_data B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void readbit(void)//读位
{
uchar ri,rem,rec,rema;
uchar address,bytenum;
address=charjiema(&comrx[3]);//解析出开始地址
bytenum=charjiema(&comrx[5]);//解析出字节数量
comtx[0]=0x02;
rec=1;
for(ri=0;ri<bytenum;ri++)
{ //
rem=bit_data[address];//读一个字节的位
rema=(rem&0xf0)>>4;
if(rema>0x09)//转换成ASIIC码
{
comtx[rec]=rema+0x37;
}
else
{
comtx[rec]=rema+0x30;
}
rec++;
rema=rem&0x0f;
if(rema>0x09)//
{
comtx[rec]=rema+0x37;
}
else
{
comtx[rec]=rema+0x30;
}
rec++;
address++;
}
comtx[rec]=0x03;//写结束字
secount=sumsdd(rec);//求和
SendString(&comtx[0]);
}
/****************************************************************************
* 名称:readbyte()
* 功能:读字节操作。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
v_variable D字节单元(全局变量)
* 出口参数:无
****************************************************************************/
void readbyte(void)
{
uchar ri,rec,rema,rem;
int remx ;
uchar address,bytenum;
address=charjiema(&comrx[3]);//解析出开始地址
address=address/2;
bytenum=charjiema(&comrx[5]);//解析出字节数量
bytenum=bytenum/2;
comtx[0]=0x02;
rec=1;
for(ri=0;ri<bytenum;ri++)
{ //把十六位的二进制转成ASIIC码
remx=v_variable[address];
// rem=(uchar)(remx>>8);
rem=(uchar)(remx&0x00ff);
rema=(rem&0xf0)>>4;
if(rema>0x09)
{
comtx[rec]=rema+0x37;
}
else
{
comtx[rec]=rema+0x30;
}
rec++;
rema=rem&0x0f;
if(rema>0x09)
{
comtx[rec]=rema+0x37;
}
else
{
comtx[rec]=rema+0x30;
}
rec++;
// rem=(uchar)(remx&0x00ff);
rem=(uchar)(remx>>8);
rema=(rem&0xf0)>>4;
if(rema>0x09)
{
comtx[rec]=rema+0x37;
}
else
{
comtx[rec]=rema+0x30;
}
rec++;
rema=rem&0x0f;
if(rema>0x09)
{
comtx[rec]=rema+0x37;
}
else
{
comtx[rec]=rema+0x30;
}
rec++;
address++;
}
comtx[rec]=0x03;
secount=sumsdd(rec);//和校验
SendString(&comtx[0]);
}
/****************************************************************************
* 名称:read16bit()
* 功能:读4位ASIIC码转换成16位INT型
* 入口参数:
reip 需要转换数据指针
* 出口参数:
rea 转换后的数据
****************************************************************************/
int read16bit(uchar *reip)//读4位ASIIC码转换成16位INT型
{
int reb,rea;
uchar re_c;
re_c=charjiema(reip);
reb=(int)(re_c);
reip++;
reip++;
re_c=charjiema(reip);
rea=(int)(re_c);
rea=rea<<8;
reb=reb&0x00ff;
rea=rea|reb;
return(rea);
}
/****************************************************************************
* 名称:writebyte()
* 功能:写字节操作。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
v_variable D字节单元(全局变量)
* 出口参数:无
****************************************************************************/
void writebyte(void)
{
uchar ri;
uchar address,bytenum;
address=charjiema(&comrx[3]); //解析出开始地址
address=address/2;
bytenum=charjiema(&comrx[5]); //解析出字节数量
bytenum=bytenum/2;
for(ri=0;ri<bytenum;ri++) //写字节
{
v_variable[address]=read16bit(&comrx[7+ri*4]);
address++;
}
SendByte(0x06); //返回正确
}
/****************************************************************************
* 名称:setbit()
* 功能:位设置1。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
bit_data B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void setbit(void)//位设置1
{
uchar address;
uchar aby,abi;
uchar abm;
address=charjiema(&comrx[1]); //解析出开始地址
aby=address/8;
abi=address%8;
abm=0x01<<abi; //置1
bit_data[aby]=bit_data[aby]|abm;
SendByte(0x06); //返回正确
}
/****************************************************************************
* 名称:clrbit()
* 功能:位清零。
* 入口参数:
comrx 接收数据缓冲区(全局变量)
bit_data B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void clrbit(void)//位清零
{
uchar address;
uchar aby,abi;
uchar abm;
address=charjiema(&comrx[1]); //解析出开始地址
aby=address/8;
abi=address%8;
abm=0x01<<abi;
abm=~abm; //清零
bit_data[aby]=bit_data[aby]&abm;
SendByte(0x06); //返回正确
}
/****************************************************************************
* 名称:SendString()
* 功能:向串口发送字符串。
* 入口参数:
sendip 要发送的数据指针
secount 要发送数据的个数(全局变量)
* 出口参数:无
****************************************************************************/
void timex(int tims)
{
char tim;
for(;tims>0;tims--)
{
tim=100;
for(;tim>0;tim--);
}
}
/****************************************************************************
* 名称:SendString()
* 功能:向串口发送字符串。
* 入口参数:
sendip 要发送的数据指针
secount 要发送数据的个数(全局变量)
* 出口参数:无
****************************************************************************/
void SendString(uchar *sendip)
{
for(;secount>0;secount--)
{
SendByte(*sendip);
sendip++;
}
}
/****************************************************************************
* 名称:SendByte()
* 功能:向串口发送字节数据。
* 入口参数:data 要发送的数据
* 出口参数:无
****************************************************************************/
/**
void SendByte(uint8 data)
{
U0THR = data; // 发送数据
while( (U0LSR&0x20)==0 );
}
**/
void SendByte(uint8 ch)
{
while (!(USART1->SR & USART_FLAG_TXE));
USART1->DR = (ch & 0x1FF);
}
/****************************************************************************
* 名称:SendString()
* 功能:向串口发送字符串。
* 入口参数:data 要发送的数据指针
* 出口参数:无
****************************************************************************/
void SendStringx(uint8 const *data)
{
while(1)
{
if(*data=='\0')break; //判断是否到了字符尾
SendByte(*data++); //发送字符
}
}
/*----------------------------------------------------------------------------
USART1_IRQHandler
Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
void USART1_IRQHandler (void) {
volatile unsigned int IIR;
uint16 i;
//struct buf_st *p;
IIR = USART1->SR;
if (IIR & USART_FLAG_RXNE) //接收中断
{ // read interrupt
USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt
i=(USART1->DR & 0x1FF); //读接收数据
switch(i)
{
case 0x02://开始字
rxcount=0;
break;
case 0x03://结束字
comrx[rxcount]=i;
rxcount++;
rxend=0;
endbit=1;
break;
case 0x06://接收正确
break;
case 0x15://接受错误
break;
default:
comrx[rxcount]=i;
rxcount++;
if(endbit)//接收到结束字
{
rxend++;
if(rxend==0x02)//接收完一条数
{
rxflish=1;//置接受完标志
endbit=0;//清接收到结束字标志2006-12-6 8:55
}
}
break;
}
}
if (IIR & USART_FLAG_TXE) //发送中断
{
USART1->SR &= ~USART_FLAG_TXE; // clear interrupt
}
} |
|