//ATmega128 AU USART1,波特率9600,modbus协议,单速,1中止位,CRC校验
//编译器 :ICC7.22
//晶振:11.0592MHZ,,外部高频石英震动器,发动时刻4.1ms
//熔丝:扩展位:0xff, 0x19af,加密位:0xff
//***********************************************************************
// 初始化去,参数界说区
//***********************************************************************
#include
#include
#include
#include
#define F_CPU11059200// 外部晶振11.0592MHz
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define baud 9600 //波特率
#define baud_setting (uint)((ulong)F_CPU/(16*(ulong)baud)-1) //设置波特率
#define baud_h (uchar)(baud_setting>>8) //设置波特率高位
#define baud_l (uchar)(baud_setting) //设置波特率方位
#define send_485 PORTE|=(1<
#define send_ok 0x01
#define RS_CLRPORTF &= ~(1 << PF1) //RS置低
#define RS_SETPORTF |= (1 << PF1) //RS置高
#define RW_CLRPORTF &= ~(1 << PF2) //RW置低
#define RW_SETPORTF |= (1 << PF2) //RW置高
#define EN_CLRPORTF &= ~(1 << PF3) //E置低
#define EN_SETPORTF |= (1 << PF3) //E置高
#define PSB_CLRPORTF &= ~(1 << PE2) //PSB置低,串口方法
#define PSB_SETPORTF |= (1 << PE2) //PSB置高,并口方法
#define LOW0
#define HIGH 1
//12864初始化指令
#define CLEAR_SCREEN0x01//清屏指令:清屏且AC值为00H
#define AC_INIT 0x02//将AC设置为00H。且游标移到原点方位
#define CURSE_ADD0x06//设定游标移到方向及图画全体移动方向(默许游标右移,图画全体不动)
#define FUN_MODE0x30//作业形式:8位根本指令集
#define DISPLAY_ON0x0c//显现开,显现游标,且游标方位反白
#define DISPLAY_OFF0x08//显现关
#define CURSE_DIR0x14//游标向右移动:AC=AC+1
#define SET_CG_AC0x40//设置AC,规模为:00H~3FH
#define SET_DD_AC0x80
#define Data_IO PORTA //液晶数据口
#define Data_DDR DDRA //数据口方向寄存器
#define D_LE0 PORTD &= ~(1 << PD4) //数码管段操控位为0,锁存端口数据
#define D_LE1 PORTD |= (1 << PD4) //数码管段操控位为1,锁存器输出与端口共同
#define W_LE0 PORTD &= ~(1 << PD5) //数码管位操控位为0
#define W_LE1 PORTD |= (1 << PD5) //数码管位操控位为1
volatile unsigned char digit[10]={“0123456789”};
volatile uchar address=0x01;//从机地址
volatile uchar RX_bit=0;//接纳中止置位标志
static uchar A1,A2,A3,A4,A5; //十进制数据转化缓存数据
uchar usart_tx_data[250];//发送数据缓存
uchar *TX_data;//发送数据copy指针变量
uchar *RX_data;//接纳数据copy指针变量
uchar usart_rx_data[250];//发送数据数组
uchar rx_data_buf[250];//发送数据缓存数组
uchar data_buf[250];//校验缓存数组
uchar rx_count=0;//发送数据个数计数
uchar tx_count=0;//接纳数据个数计数
uchar read_count=0;//接纳数据读取计数,copy
uint RX_length=0;//接纳数据长度,个数
volatile uint CRC_word=0xffff;//核算CRC校验码
volatile uint RX_CRC_word=0xffff;//接纳到CRC校验码
/*******************************************************************************
* 函数称号: LCD_write_com(unsigned char com)
* 函数功用: 液晶屏写指令
* 参数变量:unsigned char com
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void LCD_write_com(unsigned char com)
{
RS_CLR;
RW_CLR;
EN_SET;
Data_IO = com;
delay_nms(5);
EN_CLR;
}
/*******************************************************************************
* 函数称号: LCD_write_data(unsigned char data)
* 函数功用: 液晶屏写数据
* 参数变量:unsigned char data
* 大局变量: work_data_do_Tx()
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void LCD_write_data(unsigned char data)
{
RS_SET;
RW_CLR;
EN_SET;
Data_IO = data;
delay_nms(5);
EN_CLR;
}
/*******************************************************************************
* 函数称号: LCD_clear(void)
* 函数功用: 清屏
* 参数变量:
* 大局变量:
* 调用函数:LCD_write_com(uint com);
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void LCD_clear(void)
{
LCD_write_com(0x01);
delay_nms(5);
}
/*******************************************************************************
* 函数称号: DisplayCgrom(uchar addr,uchar *hz)
* 函数功用: 写汉字
* 参数变量: uchar addr,uchar *hz
* 大局变量:
* 调用函数: LCD_write_com(uint com);
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void DisplayCgrom(uchar addr,uchar *hz)
{
LCD_write_com(addr);
delay_nms(5);
while(*hz != \0)
{
LCD_write_data(*hz);
hz++;
delay_nms(5);
}
}
/*******************************************************************************
* 函数称号:WriteAddress(unsigned char x)
* 函数功用: 写地址,从左到右
* 参数变量: unsigned char x
* 大局变量:
* 调用函数: LCD_write_com(uint com);
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void WriteAddress(unsigned char x)
{
LCD_write_com(x|0x80); //地址 x + 0x80
}
/*******************************************************************************
* 函数称号: Display(void)
* 函数功用:
* 参数变量:
* 大局变量:
* 调用函数:DisplayCgrom(uchar addr,uchar *hz)
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void Display(void)
{
DisplayCgrom(0x80,”久辉电气欢迎你”);
DisplayCgrom(0x88,”旺:jingyehanxing”);
DisplayCgrom(0x90,”www.jhdq.net “);
DisplayCgrom(0x98,”电话:13816062843″);
}
/*******************************************************************************
* 函数称号: LCD_init(void)
* 函数功用:
* 参数变量:
* 大局变量:
* 调用函数:LCD_write_com(uint com)
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void LCD_init(void)
{
DDRA = 0xFF; //I/O口方向设置
DDRA |= (1 << PA5) | (1 << PA6) | (1 << PA7);
LCD_write_com(FUN_MODE);//显现形式设置
delay_nms(5);
LCD_write_com(FUN_MODE);//显现形式设置
delay_nms(5);
LCD_write_com(DISPLAY_ON);//显现开
delay_nms(5);
LCD_write_com(CLEAR_SCREEN);//清屏
delay_nms(5);
}
/*******************************************************************************
* 函数称号:get_crc(uint n)
* 函数功用: CRC校验码
* 参数变量: uint n
* 大局变量: data_buf[i] CRC_word
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
uint get_crc(uint n)
{
uchar i,j;
CRC_word=0xffff;//赋值:0xffff
for(i=0;i
CRC_word^=(uint)data_buf[i];//核算CRC_word
for(j=0;j<8;j++)
{
if(CRC_word&0x0001)
{
CRC_word=CRC_word>>1;
CRC_word^=0xa001;
}
else
{
CRC_word>>=1;
}
}
}
return CRC_word;
}
/*******************************************************************************
* 函数称号: USART_Flush( void )
* 函数功用: 改写通讯数据寄存器
* 参数变量: dummy
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void USART_Flush( void )
{
unsigned char dummy;
while ( UCSR1A & (1<
}
/*******************************************************************************
* 函数称号: USART_Receive()
* 函数功用: 串行通讯接纳
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
unsigned char USART_Receive()
{
//等候数据寄存器为空
while ( !(UCSR1A & (1<
//接纳数据
return UDR1;
}
/*******************************************************************************
* 函数称号: void USART_Transmit(uchar data)
* 函数功用:
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void USART_Transmit(uchar data)
{
//等候数据寄存器为空
while ( !( UCSR1A & (1<
//数据放入缓存器
UDR1 = data;
}
/*******************************************************************************
* 函数称号: uart1_init(void) 字符长度 8bit
* 函数功用: 串行口通讯初始化,bit:9600 ,单倍速,一中止位,校验 无
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void uart1_init(void)
{
UCSR1B=0x00;//不使能设定波特率
UCSR1A=0x00; //
UCSR1B=0x98;//接纳中止,发送使能(查询)
UCSR1C=(1<
UBRR1L=baud_l;
}
/*******************************************************************************
* 函数称号: data_do(uint temp_d)
* 函数功用: 接纳数据 16–>10进制处理 ,五位
* 参数变量: A1,A2,A3,A4,A5[uchar],temp(uint)
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void data_do(uint temp_d)//
{
A1=temp_d%10;//?
A2=(temp_d/10)%10;//
A3=(temp_d/100)%10;
A4=(temp_d/1000)%10;
A5=temp_d/10000;//
}
/*******************************************************************************
* 函数称号: uart1_rx_isr(void)
* 函数功用:中止接纳多数据
* 参数变量:
* 大局变量:usart_rx_data[rx_count], rx_count++; RX_bit;
* 调用函数:USART_Flush()
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
#pragma interrupt_handler uart1_rx_isr:iv_USART1_RXC
void uart1_rx_isr(void)
{
usart_rx_data[rx_count]=UDR1;//接纳数据
USART_Flush();//改写寄存器
rx_count++;//累计接纳数据个数
RX_bit=1;//接纳中止置位
}
/*******************************************************************************
* 函数称号: funtion_03()
* 函数功用: modbus通讯读操作(从机)
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void funtion_03()
{
;
}
/*******************************************************************************
* 函数称号: funtion_04()
* 函数功用:
* 参数变量:
* 大局变量:
* 调用函数:TX_data_set[i]
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void funtion_04()//
{
;
}
/*******************************************************************************
* 函数称号: funtion_06()
* 函数功用: modbus通讯写操作(从机)
* 参数变量:
* 大局变量: work_data_do_Tx()
* 调用函数:TX_data_set[i]
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void funtion_06()//???
{
;//EEPROM??????
}
/*******************************************************************************
* 函数称号: funtion_06()
* 函数功用:读毛病具体参数
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void funtion_07()
{
;
}
/*******************************************************************************
* 函数称号: send_code_fun()
* 函数功用: modbus发送读数据指令函数
* 参数变量:uchar addrs,uchar funtion,uint data_addr,uint data_length
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void send_code_fun(uchar addrs,uchar funtion,uint data_addr,uint data_length)
{
char i=0;//
data_buf[0]=addrs;//从机地址
data_buf[1]=funtion;//功用码
data_buf[2]=data_addr/256;
data_buf[3]=data_addr%256;//数据地址
data_buf[4]=data_length/256;//
data_buf[5]=data_length%256;//数据长度
CRC_word=get_crc(6);//CRC_word 核算
data_buf[6]=CRC_word%256;//CRC_word 低位
data_buf[7]=CRC_word/256;//CRC_word 高位
for(i=0;i<6+2;i++)
{
usart_tx_data[i]=data_buf[i];//数据放入发送缓存器
USART_Transmit(usart_tx_data[i]);//发送数据
}
}
/*******************************************************************************
* 函数称号: receive_main()
* 函数功用: 接纳主函数
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void receive_main()
{
delay_nms(300);
CLI(); //大局中止不使能
rx_count=0;//中止计数器清零
send_485;//485处于发送状况
UCSR1B=0x08; //串口初始化
delay_nms(15);//485呼应时刻
RX_length=data_buf[2]*256+data_buf[3];//取数据长度数据
RX_CRC_word=data_buf[RX_length+1]*256+data_buf[RX_length];//取CRC校验码
CRC_word=get_crc(RX_length);//核算接纳数据校验码
if(CRC_word==RX_CRC_word)//校验数据比较
{
if(data_buf[0]==address||data_buf[0]==televise_add)//地址比较
{
send_code_fun(1,3,0,1);//发送数据
UCSR1B=0x00; //通讯不使能
switch(usart_rx_data[1])//接纳数据处理
{
case 0x03:funtion_03();break;//???
case 0x04:funtion_04();break;//
case 0x06:funtion_06();break;//???
case 0x07:funtion_07();break;//???
default: break;
}
}
else ;
}
else ;
receive_485;//485处于接纳状况
UCSR1B=0x90; //通讯寄存器设置
delay_nms(15);//485呼应时刻
SEI(); //大局中止使能
}
/*******************************************************************************
* 函数称号: send_data_do(uint do_length)
* 函数功用: 发送数据
* 参数变量:
* 大局变量:
* 调用函数:get_crc(uchar n) ,
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void send_data_do(uint do_length)
{
//
//
//
//
//
CRC_word=get_crc(do_length);//CRC_word核算
data_buf[do_length]=CRC_word%256;//CRC_word 低位
data_buf[do_length+1]=CRC_word/256;//CRC_word 高位
}
/*******************************************************************************
* 函数称号: send_main(uint length)
* 函数功用:
* 参数变量:
* 大局变量: send_data_do(length);
* 调用函数:TX_data_set[i]
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void send_main(uint length)
{
uint i_tx=0;
send_485;//487处于发送状况
UCSR1B=0x08; //串行口处于发送
delay_nms(15);//485呼应时刻
send_data_do(length);//发送数据处理
for(i_tx=0;i_tx
usart_tx_data[i_tx]=data_buf[i_tx];//缓存数据放入发送数组
USART_Transmit(data_buf[i_tx]);//发送数据
USART_Flush();//改写通讯数据寄存器
}
}
/*******************************************************************************
* 函数称号: port_init(void)
* 函数功用:
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void port_init(void)
{
PORTE|=0x10;//PE4 485 DE/RE
PORTE=0xff;//
PORTB=0xff;
PORTB=0xff;
Data_IO = 0xFF; //电平设置
Data_DDR = 0xFF; //方向输出
PORTF = 0xFF; //电平设置
DDRF = 0xFF; //方向输出
PORTD=0xFF;
DDRD=0xFF;
PORTE=0xFF; //PSB对应于PE2
DDRE=0xFF;
D_LE1; //关掉数码管,避免显现乱码
W_LE1;
Data_IO=0xFF; //关数码管
W_LE0;
PSB_SET;
}
/*******************************************************************************
* 函数称号: send_TX_fun(uint length)
* 函数功用:
* 参数变量:
* 大局变量: work_data_do_Tx()
* 调用函数:TX_data_set[i]
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
XDIV = 0x00; //xtal divider
XMCRA = 0x00; //external memory
port_init();//口初始化
uart1_init();//串口通讯 1 初始化
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EICRB = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 0x00; //timer interrupt sources
ETIMSK = 0x00; //extended timer interrupt sources
receive_485;//485处于接纳状况
//all peripherals are now initialized
}
/*******************************************************************************
* 函数称号: send_TX_fun(uint length)
* 函数功用:
* 参数变量:
* 大局变量: work_data_do_Tx()
* 调用函数:TX_data_set[i]
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void du_fun()
{
USART_Transmit(0x01);//发送数据
USART_Flush();
USART_Transmit(0x03);
USART_Flush();
USART_Transmit(0x00);
USART_Flush();
USART_Transmit(0x00);
USART_Flush();
USART_Transmit(0x00);
USART_Flush();
USART_Transmit(0x01);
USART_Flush();
USART_Transmit(0x84);//CRC L
USART_Flush();
USART_Transmit(0x0a);//CRC H
USART_Flush();
UCSR1B=0x98;
}
/*******************************************************************************
* 函数称号: set_addrress()
* 函数功用:设置从机地址
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void set_addrress()
{
}
/*******************************************************************************
* 函数称号: main()
* 函数功用: 主函数
* 参数变量:
* 大局变量:
* 调用函数:
* 作者: 张奇
* 编写时刻:10-06-03
* 修正时刻: 10—07-20
* 版别:V1.0
*******************************************************************************/
void main()
{
init_devices(); //体系初始化
LCD_init(); //液晶参数初始化设置
Display();//显现
delay_nms(1000); //延时1000ms
LCD_clear(); //清屏
send_code_fun(1,6,0,0×190);//发送写数据
// send_code_fun(1,3,0,1);//发送写数据
//写格局:地址(8bit) 功用(8bit) 数据地址(16bit) 写数据(16bit)
//读格局:地址(8bit) 功用(8bit) 数据地址(16bit) 数据个数(16bit)
SEI(); //开大局中止
for(;;)
{
delay_nms(2000);//时刻很重要,
if(RX_bit==1)//处理接纳中止
{
RX_bit=0;//清中止标志
CLI();//大局中止无效
RX_data=&usart_rx_data[0];//指针接纳数组首地址
for(read_count=0;read_count
rx_data_buf[read_count]=*RX_data++;//指针仿制数组
}
WriteAddress(0x80);//写地址
delay_nms(5); //延时
data_do(rx_data_buf[0]); //数据处理
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//写显现数据
delay_nms(5);
WriteAddress(0x82);//
data_do(rx_data_buf[1]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
WriteAddress(0x84);//
data_do(rx_data_buf[2]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
WriteAddress(0x86);//
data_do(rx_data_buf[3]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
WriteAddress(0x90);//
data_do(rx_data_buf[4]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
WriteAddress(0x92);//
data_do(rx_data_buf[5]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
WriteAddress(0x94);//
data_do(rx_data_buf[6]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
WriteAddress(0x96);//
data_do(rx_data_buf[7]); //
delay_nms(5);
LCD_write_data(digit[A3]);//
delay_nms(5);
LCD_write_data(digit[A2]);//
delay_nms(5);
LCD_write_data(digit[A1]);//
delay_nms(5);
rx_count=0;//接纳中止次数清零
SEI(); //开大局中止
}
}
}