main.c
/****************************************************************************/
/* */
/* Copyright (c) 2016, 老马工作室 */
/* All rights reserved. */
/* */
/* Email:pcwebmaster@163.com */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c */
/* 版 本:Version 1.0 */
/* 描 述:串行口中断带通讯协议测试 */
/* 主控芯片:PIC16F1937 */
/* 晶振频率:4MHz */
/* 作 者:pcwebmaster(北极狼) */
/* 函 数: */
/* system_init */
/* com_send_command */
/* com_command_receive */
/* CalCRC16_1021 */
/* command_decoder */
/* send_command */
/* 测 试: 发送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15 */
/* 测试现象: */
/* 历史记录:20016.02.19测试通过 */
/* 北极狼 20016-02-19 Creat Inital version. (Version 1.0) */
/****************************************************************************/
#include "pic.h"
#include "comint.h"
__CONFIG(FOSC_INTOSC&CLKOUTEN_OFF&MCLRE_ON&WDTE_OFF);//&PWRTE_ON&BOREN_ON
#define _XTAL_FREQ 4000000L //内部4MHz
//*******************************************************************//
// 系统初始化
//*******************************************************************//
void System_Init(void)
{
OSCCON = 0b01101000; //内部4MHz
OSCTUNE= 0b00000000; //出厂校准
ADCON1 = 0b10110000; //内部Frc Vref = VDD
ADCON0 = 0b00010001; //ADON = 1 As AN4
TRISA = 0b00100000; //RA0-RA3输出、RA5输入
ANSELA = 0b00100000; //RA5 模拟输入
TRISB = 0b00001111; //RB0-RB3触摸按键
ANSELB = 0b00001111; //4个触摸按键
WPUB = 0b00000000; //无上拉
IOCBP = 0b00000000; //关电平变化中断
IOCBN = 0b00000000;
TRISD = 0b00000000; //PORTD输出
ANSELD = 0b00000000; //数字 I/O
TRISC = 0b10011000; //串口 I2C
TRISE = 0b00000000; //PORTE输出
ANSELE = 0b00000000; //数字 I/O
WPUE = 0b00000000; //无上拉
LATA = 0x00;
LATB = 0x00;
LATC = 0x00;
LATD = 0x00;
LATE = 0x00;
}
//*******************************************************************//
// TMR0定时初始化
//*******************************************************************//
void TMR0_Init(void)
{
OPTION_REG = 0b11010011;
TMR0IF = 0;
TMR0IE = 1;
}
//*******************************************************************//
// 主程序部分
//*******************************************************************//
void main(void)
{
INT8U *str="Hello World! nrSerial test normalnr";
INT8U *end="nr";
__delay_ms(10);
System_Init(); //系统初始化
CLRWDT(); //WDT看门狗
TMR0_Init(); //TMR0初始化
Serial_port_init(); //UART初始化
PEIE = 1; //外设中断允许
GIE = 1; //总中断允许
buff_init();
Send_String(str);
Send_String(end);
while (1)
{
com_command_receive();
}
}
COMINT.C
/****************************************************************************/
/* */
/* Copyright (c) 2016, 老马工作室 */
/* All rights reserved. */
/* */
/* Email:pcwebmaster@163.com */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c */
/* 版 本:Version 1.0 */
/* 描 述:串行口中断带通讯协议测试 */
/* 主控芯片:PIC16F1937 */
/* 晶振频率:4MHz */
/* 作 者:pcwebmaster(北极狼) */
/* 函 数: */
/* system_init */
/* com_send_command */
/* com_command_receive */
/* CalCRC16_1021 */
/* command_decoder */
/* send_command */
/* 测 试: 发送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15 */
/* 测试现象: */
/* 历史记录:20016.02.19测试通过 */
/* 北极狼 20016-02-19 Creat Inital version. (Version 1.0) */
/****************************************************************************/
#include
#include "comint.h"
uint8_t pint_buf[MAX_RINTL]; /* 串口接收缓冲区 */
uint8_t pint_read; /* 串口缓冲区读指针 */
uint8_t pint_write; /* 串口缓冲区写指针 */
//uint8_t psend_int; /* 串口发送允许标志 */
uint8_t serial_flag = 0; /* 串口接收数据标志位 */
uint8_t prec_buf[MAX_COMMAND_LEN]; /* 命令接收缓冲区 */
uint8_t prec_num; /* 命令接收缓冲区字节数 */
uint8_t serial_lengthl = 0; /* 消息命令长度低8位 */
uint16_t serial_length = 0; /* 消息命令长度16位 */
uint8_t ADDRESS[2]={ZU,ZHAN}; /* byte0:通讯组地址, byte1:开发板地址 */
//-----------------------------------------------------------------
// 串口初始化
//-----------------------------------------------------------------
void Serial_port_init(void)
{
unsigned char BaudRate = 0;
BaudRate = BAUDRATE;
switch(BaudRate)
{
case 1:
BRGH = 0; //2400
SPBRG = 25;
break;
case 2:
BRGH = 0; //4800
SPBRG = 12;
break;
case 3:
BRGH = 1; //9600
SPBRG = 25;
break;
case 4:
BRGH = 1; //19200
SPBRG = 12;
break;
}
SYNC = 0; // asynchronous
SPEN = 1; // enable serial port pins
CREN = 1; // enable reception
TXEN = 1; // enable Send
SREN = 0; // no effect
TXIE = 0; // Disable TX interrupts
RCIE = 1; // Enable RX interrupts
}
//-----------------------------------------------------------------
// 串口发送一个字节
//-----------------------------------------------------------------
void com_send_command(char Onebyte)
{
TXREG = Onebyte;
while(TRMT);
__delay_ms(1);//4M晶体最少需要1MS延时,??
}
//------------------------------------------------------------------
// (串口接收)中断程序(缓冲满时数据前移)
//------------------------------------------------------------------
void interrupt Serial_Port_Recv_ISR(void)
{
uint8_t temp;
uint8_t temp1;
if(TMR0IE && TMR0IF) //4MHz 2.5ms
{
TMR0IF = 0;
TMR0 = 0x65;
CLRWDT();
}
if(RCIE && RCIF)
{
temp1 = RCREG; //读取数据
temp = pint_write + 1; /* 判断是否可以写入 */
if (temp == MAX_RINTL)
{
temp=0;
}
if (temp != pint_read)
{
pint_buf[pint_write] = temp1; /* 读取数据 */
pint_write = temp;
}
}
}
void buff_init(void)
{
uint8_t loop;
loop = RCREG; /* 清串口缓冲区 */
for (loop=0; loop
pint_buf[loop] = 0;
}
}
////////////////////////////以上需要修改移植,以下直接移植并添加代码/////////////////////////////////////////////
//------------------------------------------------------------------
// 向PC机发送字符串
//------------------------------------------------------------------
void Send_String(char *str)
{
while(*str) //检测str是否有有效
{
com_send_command(*str++);
}
}
/* 串口接收数据处理 */
void com_command_receive(void)
{
uint8_t var1,var4;
uint16_t crc_data = 0;
var4 = pint_read;
if (var4 != pint_write)
{
var1 = pint_buf[var4];
var4 = var4+1;
if (var4 >= MAX_RINTL)
var4=0;
pint_read = var4;
switch(serial_flag)
{
case 0: /*收到起始位*/
if (var1 == SYN)
{
serial_flag = 1;
//com_send_command(0x01); //测试
}
else
{
serial_flag = 0;
}
break;
case 1:/*收到起始位*/
if (var1 == SYN)
{
serial_flag = 2;
//com_send_command(0x02); //测试
}
else
{
serial_flag = 0;
}
break;
case 2:/*收到同步位*/
if (var1 == STX)
{
serial_flag = 3;
//com_send_command(0x03);//测试
}
else
{
serial_flag = 0;
}
break;
case 3: /*收到组地址*/
if (var1 == ADDRESS[0])
{
serial_flag = 4;
prec_num = 1;
prec_buf[0] = var1;
//com_send_command(0x04); //测试
}
else
{
serial_flag = 0;
}
break;
case 4:/*收到本机地址或者广播地址*/
if ( (var1 == ADDRESS[1]) || (var1 == 0) )
{
prec_num = 2;
prec_buf[1] = var1;
serial_flag = 5;
//com_send_command(0x05); //测试
}
else
{
serial_flag = 0;
}
break;
case 5:/*数据长度*/
prec_num = 3;
prec_buf[2] = var1;
serial_lengthl = var1;
serial_flag = 6;
//com_send_command(0x06);//测试
break;
case 6:
prec_num = 4;
prec_buf[3] = var1;
serial_length |= var1;
serial_length = ( (serial_length << 8) & 0xff00 ) + serial_lengthl + 3;
serial_flag = 7;
//com_send_command(0x07);//测试
break;
case 7:
prec_buf[prec_num] = var1;
prec_num++;
serial_length--;
if (serial_length == 0)
{
crc_data = CalCRC16_1021(prec_buf, prec_num - 2); /* 计算crc校验和(从组地址开始到ETX )*/
if ( ( (crc_data & 0x00ff) == prec_buf[prec_num - 2]) && ( ( (crc_data >>8) & 0x00ff) == prec_buf[prec_num - 1]) ) /* 校验和正确 */
{
prec_num = 1;
var1 = 0;
if ( (prec_buf[4] >= 0x31) && (prec_buf[4] <= 0x3b) ) /* 命令有效 */
{
if (prec_buf[1] != 0x00) /* 如果不是广播地址则回应ACK*/
com_send_command(0x49);//测试 msg_last_push(MSG_ACK,0);
// send_command(ACK); //测试
command_decoder(); /* 如果校验和正确,则进行命令解码 */
}
else
{
send_command(NAK); //测试
}
}
else
{
send_command(NAK); //测试
}
serial_flag = 0;
prec_num = 1;
}
break;
default:
serial_flag = 0;
prec_num = 1;
break;
}
}
}
/* 命令解码子程序 */
void command_decoder(void)
{
// uint8_t i = 0;
if (prec_buf[4] == 0x31) /* 设置报警阈值 */
{
com_send_command(0x11);//测试
return;
}
else if (prec_buf[4] == 0x32) /* 请求报警阈值 */
{
com_send_command(0x12);//测试?
return;
}
else if (prec_buf[4] == 0x33) /* 修改当前时间 */
{
com_send_command(0x13);//测试
return;
}
else if (prec_buf[4] == 0x34) /* 请求当前时间 */
{
com_send_command(0x14);//测试
return;
}
else if (prec_buf[4] == 0x35) /* 请求当前数据 */
{
com_send_command(0xAA);//测试
//__nop();
com_send_command(0x15);//测试
return;
}
else if (prec_buf[4] == 0x36) /* 请求看门狗信息*/
{
com_send_command(0x16);//测试
return;
}
else if (prec_buf[4] == 0x37) /* 请求报警情况 */
{
com_send_command(0x17);//测试
return;
}
else if (prec_buf[4] == 0x38) /* 配置设备地址 */
{
ADDRESS[0] = prec_buf[5]; /* 通讯组地址 */
ADDRESS[1] = prec_buf[6]; /* 开发板地址 */
com_send_command(0x181);//测试
return;
}
else if (prec_buf[4] == 0x39) /* 请求设备地址 */
{
com_send_command(0x19);//测试
return;
}
else if (prec_buf[4] == 0x3a) /* 控制模拟量输出 */
{
com_send_command(0x1A);//测试?
return;
}
else if (prec_buf[4] == 0x3b) /* 控制开关量输出 */
{
com_send_command(0x1B);//测试
return;
}
// if (prec_buf[4] == 0x00) /* 如果是广播地址 */
// {
// com_send_command(SYN);
// com_send_command(0x00);
// com_send_command(SYN);
// return;
// }
}
/* 向PC主机发送消息帧,入口参数:消息类型 */
void send_command(uint8_t command)
{
switch (command)
{
case ACK:
com_send_command(SYN);
com_send_command(SYN);
com_send_command(ACK);
break;
case NAK:
com_send_command(SYN);
com_send_command(SYN);
com_send_command(NAK);
break;
default:
break;
}
}
/*计算CRC校验和使用MTT(0X1021)
参数:
pBuff 为需计算CRC的缓冲区的头指针
BufferLen 缓冲区长度(以字节计)
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen)
{
u_short i;
uint8_t j;
u_short crc16 = 0;
u_short mask = 0x1021;
uint8_t *pByteBuffer;
uint8_t tmpbyte;
u_short calval;
pByteBuffer = &x[0];
for (i = 0; i < BufferLen; i++)
{
tmpbyte = *pByteBuffer;
calval = tmpbyte << 8;
for (j = 0; j < 8; j++)
{
if ((crc16 ^ calval) & 0x8000)
crc16 = (crc16 << 1) ^ mask;
else
crc16 <<= 1;
calval <<= 1;
}
pByteBuffer++;
}
return crc16;
}
COMINT.h
#ifndef __COMINT_H__
#define __COMINT_H__
#include
#include
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000UL //4M晶振
#endif
#define BAUDRATE 3 //定义波特率 9600 N 8 1
#define INT8U unsigned char
#define INT16U unsigned int
#define uint8_t unsigned char
#define u_short unsigned int
#define uint16_t unsigned int
#define ZU 0x01 /*组地址*///通讯地址修改这两项
#define ZHAN 0x02 /*站地址*///通讯地址修改这两项
#define MAX_RINTL 16 /* 串口接收缓冲区长度 */
#define SYN 0x16 /* 通讯同步位*/
#define STX 0x02 /* 通讯起始位*/
#define ETX 0x03 /* 通讯结束位*/
#define ACK 0x06
#define NAK 0x15
#define MSG_ACK 2 /* 正确应答信息 */
#define MSG_NAK 3 /* 错误应答信息 */
#define MAX_COMMAND_LEN 16 /* 串口接受命令长度 */
extern char str_test[25] ;
extern uint8_t pint_read; // 串口缓冲区读指针 */
extern uint8_t pint_write; // 串口缓冲区写指针
//extern uint8_t data psend_int; // 串口发送允许标志
extern uint8_t pint_buf[MAX_RINTL]; // 串口接收缓冲区
extern uint8_t serial_flag; /* 串口接收数据标志位 */
extern uint8_t prec_buf[MAX_COMMAND_LEN];/* 命令接收缓冲区 */
/* 串口初始化*/
void Serial_port_init(void);
/* 串口发送一个字节 */
void com_send_command(char Onebyte);
void Send_String(char *str);// 向PC机发送字符串
/* 串口接收数据处理 */
void com_command_receive(void);
/* 串口接收初始化 */
void buff_init(void);
///* 串口接收一字节数据 */
//unsigned char UartReadChar(void); //reentrant
/*计算CRC校验和使用MTT(0X1021)
参数:
pBuff 为需计算CRC的缓冲区的头指针
BufferLen 缓冲区长度(以字节计)
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen);
/* 命令解码子程序 */
void command_decoder(void);
/* 向主机发送消息帧,入口参数:消息类型 */
void send_command(uint8_t command);
#endif
上一篇:PIC单片机入门指南
下一篇:最后一页
推荐阅读
史海拾趣
虹冠电子自成立以来,一直将技术创新作为公司发展的核心动力。早期,虹冠电子就投入大量资源研发AC-DC模拟电源IC,成功推出了一系列高效能、低能耗的产品,迅速在市场上建立了良好的口碑。随着技术的不断迭代,虹冠电子在电源管理技术方面取得了显著优势,尤其在电竞电源供应器领域,凭借卓越的性能和稳定性,赢得了众多专业用户和消费者的认可。
DMS非常重视人才的培养和引进。公司建立了完善的人才选拔和激励机制,吸引了一批高素质的专业人才加入。这些人才在技术研发、市场营销、生产管理等方面发挥了重要作用,为公司的快速发展提供了有力保障。同时,DMS还注重员工的培训和发展,为员工提供了广阔的职业发展空间。
为了确保产品质量,FILTRONETICS始终将质量管理放在首位。公司建立了完善的质量管理体系,从原材料采购、生产制造到产品检测、售后服务等各个环节都严格把关。同时,公司还引入了先进的检测设备和技术手段,对产品进行全方位的质量检测和控制。这些措施不仅确保了产品的稳定性和可靠性,也提升了公司的品牌形象和市场声誉。
随着产品线的不断丰富和市场的扩大,CML逐渐意识到品质管理的重要性。公司开始引入先进的质量管理体系,对产品的研发、生产、销售等各个环节进行严格把控。通过持续改进和优化流程,CML成功提升了产品的品质和可靠性,赢得了客户的广泛认可。同时,公司还建立了完善的售后服务体系,为客户提供及时、专业的技术支持和服务,进一步提升了客户满意度。
随着产品线的不断丰富和市场的扩大,CML逐渐意识到品质管理的重要性。公司开始引入先进的质量管理体系,对产品的研发、生产、销售等各个环节进行严格把控。通过持续改进和优化流程,CML成功提升了产品的品质和可靠性,赢得了客户的广泛认可。同时,公司还建立了完善的售后服务体系,为客户提供及时、专业的技术支持和服务,进一步提升了客户满意度。
在快速发展的同时,Dongguan City Niuhang Electronics Co.LTD始终关注社会责任和可持续发展。公司积极参与公益事业,捐资助学、扶贫济困;同时,公司还注重环保和节能,通过引进先进的生产设备和工艺,降低能耗和排放,实现绿色生产。这些举措不仅提升了公司的社会形象,也为公司的可持续发展注入了新的动力。
请注意,以上故事为虚构内容,旨在展示Dongguan City Niuhang Electronics Co.LTD可能经历的发展阶段和事件。实际情况可能有所不同,具体信息请参考公司官方发布的相关资料。
问个s3c2410的DMA和LCD问题,nXDreq,nXDACK应接到哪里去?找了个原理图没看明白 在应用层往LCD输出图像时,可以这样写: unsigned long *nPhysicalAddress = 0x30000000;(frame buffer address) 修改nPhysicalAddress 指向的内存即可 0x30000000是怎么得出的?和硬件连接有什么关系?我下了个原理图,好像不全,反正没看明白 ...… 查看全部问答∨ |
|
我在wince6.0上开发sql ce 在建好一个数据库后,允许用户修改数据库中的内容,但是修改后却保存不了,数据库中还是原始内容。 大家有知道为什么吗? 相关代码如下(就是用了update方法): this.table2TableAdapter.Update(this.testdbDataSet1 ...… 查看全部问答∨ |
|
用电位器输出一个电压值,从我watch窗口看到的ADCresult值都在变化,变化比较大。如0xabc0,b为都会能差4,帮忙分析一下可能那里设置不对。谢谢!… 查看全部问答∨ |
|
从参加抢LM3S811的活动后,每天都期待啊,终于在4.26的下午,顺风快递发来信息去取快递,其实已经料到是811到啦,好兴奋的跑到校门口外迎接顺风,领到包裹后,回寝室迫不及待的打开它,没错是811 。用811把我以前的LCD有重新驱动了起来,下面是我这 ...… 查看全部问答∨ |
下面是一段简单的完整通讯程序,实现功能:将接受的数据原样送回。但是觉得南航教程中以下这段程序是不是少了一个子程,就是用于接收PC机发给MSP430的数据,并将接收到的数据放至发送缓存器? #include <msp430x44x.h>void main(void){WDT ...… 查看全部问答∨ |