×
嵌入式 > 嵌入式开发 > 详情

ATmega128学习(MOdbus串口通信)

发布时间:2020-08-21 发布时间:
|
//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 receive_485 PORTE&=~(1< #define televise_add 0xff
#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< dummy = UDR1;
}
/*******************************************************************************
* 函数名称: 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<|(1<|(1<|(1<|(1<|(1<|(1<|(1<|(1< UBRR1H=baud_h; //设置波特率
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()
{
|(1<|(1<|(1<|(1<|(1<|(1<|(1<|(1<


;
}
/*******************************************************************************
* 函数名称: 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,0x190);//发送写数据
// 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(); //开全局中断
}
}
}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
django是什么_django能做什么