当前位置:文档之家› 波特率自适应技术在DSP5402上的应用之C

波特率自适应技术在DSP5402上的应用之C

波特率自适应技术在DSP5402上的应用之C
波特率自适应技术在DSP5402上的应用之C

波特率自适应技术在DSP5402上的应用之C++测试程序

菜农HotPower@https://www.doczj.com/doc/087381967.html,

2005.6.33 21:58 于西安大雁塔村队部

菜地: https://www.doczj.com/doc/087381967.html,

-------------------------------------------------*/

#include //C语言可以用stdio.h

#include //C语言可以用string.h

#include "C5402DEF.h"//DSP菜鸟HotPower创建

#include "class.h"

#define ccsdebug 1//1--IO模拟SPI; 0--硬件McBSP模块

extern "C" interrupt void Timer0Isr();//注意加extern "C"

extern "C" interrupt void Timer1Isr();

extern "C" interrupt void Eint0Isr();

extern "C" interrupt void Eint1Isr();

extern "C" interrupt void Eint2Isr();

extern "C" interrupt void Eint3Isr();

SystemObj::SystemObj(void)

{

Disable();//关中断

SREG->IMR = 0x0000;//

SREG->IFR = 0xffff;//清除

//设置0x0080为中断向量表首址,在第2个128页内。

SREG->PMST = (0x01 << PMST_IPTR) | (1 << PMST_MP_MC) | (1 << PMST_OVLY); // SREG->PMST |= (1 << PMST_DROM);//数据可const.

/*---------------------------------------------------------------------------

若:设置0x0100为中断向量表首址,在第3个128页内。

则:*.cmd文件应该改为:

PAGE 0: VECS: origin=0x0100, length=0x66

则:

SREG->PMST = (0x02 << PMST_IPTR) | (1 << PMST_MP_MC) | (1 << PMST_OVLY); ----------------------------------------------------------------------------*/

SystemInit();//系统初始化

}

void SystemObj::SystemInit(void)

{

PllInit();//PLL初始化

TIMER0Init();

TIMER1Init();

EintInit();

/*--------------------------------------------------------

注意以下2个变量的作用域的不同

--------------------------------------------------------*/

if (::SystemRamTest != 0x55aa) {//全局变量SystemRamTest

::SystemRamTest = 0x55aa;//改写全局变量

}

if (SystemRamTest != 0x55aa) {//类成员变量SystemRamTest

SystemRamTest = 0x55aa;//改写类成员变量

}

::IOXF = 0;

}

void SystemObj::PllInit(void)

{

volatile unsigned int start;

SREG->SWWSR = 0x2000;

do {

SREG->CLKMD = 0;

__nop();

}

while(SREG->CLKMD & (1 << CLKMD_PLLSTATUS));

// SREG->CLKMD = (0 << CLKMD_PLLMUL) | (30 << CLKMD_PLLCOUNT) | (1 << CLKMD_PLLONOFF) | (1 << CLKMD_PLLNDIV) | (1 << CLKMD_PLLSTATUS);//10M

SREG->CLKMD = (9 << CLKMD_PLLMUL) | (30 << CLKMD_PLLCOUNT) | (1 << CLKMD_PLLONOFF) | (1 << CLKMD_PLLNDIV) | (1 << CLKMD_PLLSTATUS);//100M

// SREG->CLKMD = (14 << CLKMD_PLLMUL) | (30 << CLKMD_PLLCOUNT) | (1 <<

CLKMD_PLLONOFF) | (1 << CLKMD_PLLNDIV) | (1 << CLKMD_PLLSTATUS);//150M

for (start = 0; start < 10000; start ++);//等待外设上电复位正常结束

}

void SystemObj::TIMER0Init(void)

{

TIMER0->TCR = (1 << TCR_TSS);//关闭定时器0

TIMER0->PRD = 60000;//设置定时周期

TIMER0->TIM = 60000;//设置定时计数器

TIMER0->TCR &= ~(1 << TCR_TSS);//启动定时器0

SREG->IMR |= (1 << IMR_TINT0);//允许TINT0中断

}

void SystemObj::TIMER1Init(void)

{

TIMER1->TCR = (1 << TCR_TSS);//关闭定时器1

TIMER1->PRD = 0xffff;//设置定时周期

TIMER1->TIM = 0xffff;//设置定时计数器

// TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

// SREG->IMR |= (1 << IMR_TINT1);//允许TINT1中断

}

void SystemObj::EintInit(void)

{

SREG->IMR |= (1 << IMR_INT0);//允许INT0中断

SREG->IMR |= (1 << IMR_INT1);//允许INT1中断

SREG->IMR |= (1 << IMR_INT2);//允许INT2中断

SREG->IMR |= (1 << IMR_INT3);//允许INT3中断

}

LcdObj::LcdObj(void)

{

LcdInit();

}

void LcdObj::LcdSpiSetup(void)

{

#if (ccsdebug == 0)

/*-----------------------------------------------------------

硬件McBSP模块配置为SPI接口

实验目的:

演练硬件McBSP模块配置为SPI接口的应用。

------------------------------------------------------------*/

McBSP1->SPSA = SPCR1;

McBSP1->SPSD = 0;

// McBSP1->SPSD &= ~(1 << SPCR1_RRST);//禁止串口接收

_delay_loop_(1);//延时等待

McBSP1->SPSA = SPCR2;

McBSP1->SPSD = 0;

// McBSP1->SPSD &= ~(1 << SPCR2_XRST);//禁止串口发送

_delay_loop_(1);//延时等待

McBSP1->SPSA = SPCR1;

McBSP1->SPSD = (0x02 << SPCR1_CLKSTP);//CLKSTP=10b

_delay_loop_(1);//延时等待

McBSP1->SPSA = PCR;

McBSP1->SPSD = (1 << PCR_FSXM) //设置FSX引脚为输出,控制LCD12864的片选信号SS | (0 << PCR_FSXP) //FSX引脚平时输出低电平(LCD12864的片选信号SS无效)

| (1 << PCR_CLKXM) //设置CLKX引脚为输出

| (1 << PCR_CLKXP);//CLKXP引脚平时输出高电平

_delay_loop_(1);//延时等待

McBSP1->SPSA = SRGR1;

McBSP1->SPSD = (0x07 << SRGR1_FWID) //0x00~0x07~0xff

| (0x80 << SRGR1_CLKGDV);//速率0x80

_delay_loop_(1);//延时等待

McBSP1->SPSA = SRGR2;

McBSP1->SPSD = (1 << SRGR2_CLKSM);//

_delay_loop_(1);//延时等待

McBSP1->SPSA = RCR1;

McBSP1->SPSD = (0x00 << RCR1_RFRLEN1);//8BIT

_delay_loop_(1);//延时等待

McBSP1->SPSA = XCR1;//延时等待

McBSP1->SPSD = (0x00 << XCR1_RFRLEN1);//8BIT

_delay_loop_(1);//延时等待

McBSP1->SPSA = RCR2;

McBSP1->SPSD = (0x02 << RCR2_RDATDLY);//0x01

_delay_loop_(1);//延时等待

McBSP1->SPSA = XCR2;

McBSP1->SPSD = (0x02 << XCR2_RDATDLY);//0x01

_delay_loop_(1);//延时等待

McBSP1->SPSA = SPCR2;

McBSP1->SPSD |= (1 << SPCR2_GRST) | (1 << SPCR2_XRST) | (1 << SPCR2_FRST);

_delay_loop_(1);//延时等待

#else

/*-----------------------------------------------------------

硬件McBSP模块配置为普通IO软件模拟SPI时序

实验目的:

演练硬件McBSP模块配置为普通IO的应用.以备IO紧缺时急用。

------------------------------------------------------------*/

McBSP1->SPSA = SPCR1;

McBSP1->SPSD = 0;

McBSP1->SPSD &= ~(1 << SPCR1_RRST);//禁止串口接收

McBSP1->SPSA = SPCR2;

McBSP1->SPSD = 0;

McBSP1->SPSD &= ~(1 << SPCR2_XRST);//禁止串口发送

McBSP1->SPSA = PCR;

McBSP1->SPSD = (1 << PCR_XIOEN) | (1 << PCR_RIOEN);//设置收发为IO接口,DX输出,DR,CLKS输入 McBSP1->SPSD |= (1 << PCR_FSXM) | (1 << PCR_CLKXM);//设置FSX,CLKX可做IO输出

McBSP1->SPSD |= (1 << PCR_FSRM) | (1 << PCR_CLKRM);//设置FSR,CLKR可做IO输出

McBSP1->SPSD &= ~(1 << PCR_FSXP);//FSX信号=0

McBSP1->SPSD |= (1 << PCR_CLKXP);//CLKX信号=1

McBSP1->SPSD |= (1 << PCR_DX_STAT);//DX信号=1

}

void LcdObj::LcdInit(void)

{

_delay_loop_(1000);//延时等待

LcdSpiSetup();

/*---------------------------------------------------

LCD模块上电等待延时

----------------------------------------------------*/

_delay_loop_(1000);//延时等待

LcdClearBuffer();

LcdSendCommand(0x20);//发送4位控制命令

// LcdSendCommand(0x30);//发送8位控制命令//与8位4位无关!!!

LcdSendCommand(0x02);//发送位址归位命令,设定DDRAM位址计数器为0 LcdSendCommand(0x04);//发送进入点命令

LcdSendCommand(0x0c);//发送开显示关光标命令

LcdSendCommand(0x01);//发送清除显示命令

LcdSendCommand(0x80);//发送设定DDRAM地址0x00命令

//Keil C51汉字0xfd出错测试

// SetLcdDisplayPos(0, 0);//汉字定位到上行左端

// LcdDisplay("褒饼昌除待谍洱俘");

// LcdDisplay("1234567812345678");

// SetLcdDisplayPos(1, 0);//汉字定位到上行左端

// LcdDisplay("庚过糊积箭烬君魁");

// LcdDisplay("1234567812345678");

// SetLcdDisplayPos(2, 0);//汉字定位到上行左端

// LcdDisplay("例笼慢谬凝琵讫驱");

// LcdDisplay("1234567812345678");

// SetLcdDisplayPos(3, 0);//汉字定位到上行左端

// LcdDisplay("三升数她听妄锡淆");

// LcdDisplay("1234567812345678");

}

void LcdObj::LcdSend(unsigned char cData)

{

cData &= 0xff;

#if (ccsdebug == 0)

McBSP1->DXR1 = cData;//发送串行数据或命令

_delay_loop_(1);//延时等待

McBSP1->SPSA = SPCR2;

while((McBSP1->SPSD & (1 << SPCR2_XRDY)) == 0) {//等待发送结束

__nop();

__nop();

_delay_loop_(1);//延时等待

#else

unsigned int i;

McBSP1->SPSA = PCR;

for (i = 0; i < 8; i ++) {

McBSP1->SPSD &= ~(1 << PCR_CLKXP);//CLKX信号=0

_delay_loop_(1);//延时等待

if (cData & 0x80) {//MSB最高位为1时

McBSP1->SPSD |= (1 << PCR_DX_STAT);//DX信号=1

}

else {

McBSP1->SPSD &= ~(1 << PCR_DX_STAT);//DX信号=0

}

cData <<= 1;

_delay_loop_(1);//延时等待

McBSP1->SPSD |= (1 << PCR_CLKXP);//CLKX信号=1

_delay_loop_(1);//延时等待

}

McBSP1->SPSD |= (1 << PCR_DX_STAT);//DX信号=1

_delay_loop_(1);//延时等待

#endif

}

/*--------------------------------------------------------

发送8位LCD控制命令

--------------------------------------------------------*/

//__inline

void LcdObj::LcdSendCommand(unsigned char cCommand)

{

/*--------------------------------------------------------

发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)

--------------------------------------------------------*/

#if (ccsdebug == 1)

McBSP1->SPSD |= (1 << PCR_FSXP);//IO模拟控制FSX信号=1 _delay_loop_(1);//延时等待

#endif

LcdSend(0xf8);//发送LCD控制命令

LcdSend(cCommand & 0xf0);//发送高4位LCD控制命令

LcdSend((cCommand << 4) & 0xff);//发送低4位LCD控制命令

#if (ccsdebug == 1)

McBSP1->SPSD &= ~(1 << PCR_FSXP);//IO模拟控制FSX信号=0 #endif

if (cCommand == 0x01) _delay_loop_(160);//延时等待

else _delay_loop_(72);//st7920要求等待72uS

}

/*--------------------------------------------------------

发送8位LCD显示数据

--------------------------------------------------------*/

//__inline

void LcdObj::LcdSendData(unsigned char cData)

{

cData &= 0xff;

/*--------------------------------------------------------

发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)

--------------------------------------------------------*/

#if (ccsdebug == 1)

McBSP1->SPSD |= (1 << PCR_FSXP);//IO模拟控制FSX信号=1 _delay_loop_(1);//延时等待

#endif

LcdSend(0xfa);//发送LCD显示数据

LcdSend((cData & 0xf0) & 0xff);//发送高4位LCD显示数据

LcdSend((cData << 4) & 0xff);//发送低4位LCD显示数据

#if (ccsdebug == 1)

McBSP1->SPSD &= ~(1 << PCR_FSXP);//IO模拟控制FSX信号=0 #endif

_delay_loop_(72);//st7920要求等待延时72uS

}

//__inline

void LcdObj::SetLcdDisplayPos(unsigned int row, unsigned int col) {

row &= 0x03;//LCD12864为4行汉字

col &= 0x0f;//每行8个汉字16个字符

LcdRow = row;

LcdCol = col;

LcdRowWriteEnable[row] = true;//允许此行刷新汉字显示

}

//__inline

void LcdObj::LcdClearBuffer(void)

{

unsigned int i, j;

for (i = 0;i < 4;i ++) {

for (j = 0;j < 16; j ++) {

LcdBuffer[i][j] = ' ';

}

LcdRowWriteEnable[i] = true;//允许此行刷新汉字显示

}

LcdRow = 0;

LcdCol = 0;

}

//__inline

void LcdObj::LcdDisplayBuffer(void)

{

unsigned int i, j;

for (i = 0; i < 4; i ++) {//LCD12864为4行汉字

if (LcdRowWriteEnable[i]) {//允许此行刷新汉字显示

LcdSendCommand(0x80 + (i & 1) * 16 + (i >> 1) * 8);//移动光标 _delay_loop_(1);//延时等待

for (j = 0; j < 16; j ++) {//每行8个汉字16个字符

LcdSendData(LcdBuffer[i][j]);//刷新显示字符

_delay_loop_(1);//延时等待

}

LcdRowWriteEnable[i] = false;//过后不允许此行刷新汉字显示 _delay_loop_(1);//延时等待

}

}

}

//__inline

void LcdObj::LcdDisplay(const char * string)

{

while(*string) {

LcdBuffer[LcdRow][LcdCol ++] = (unsigned char)*string ++;

}

}

void LcdObj::LcdDisplay(double val)

{

char string[17];

std::sprintf(string, "%5.2f", val);//注意std::

LcdDisplay(string);

}

void LcdObj::LcdDisplay(unsigned int val)

{

char string[17];

std::sprintf(string, "%04X", val);//注意std::

LcdDisplay(string);

void LcdObj::LcdDisplay(unsigned long val)

{

//char string[17];

LcdDisplay((unsigned int)(val >> 16));

LcdDisplay((unsigned int)(val & 0xffff));

// std::sprintf(string, "%08LX", (unsigned long)val);//注意std:: // LcdDisplay(string);

}

void LcdObj::LcdDisplay(unsigned char hexstr[], unsigned int len) {

unsigned char ch;

for (int i = 0; i < len; i ++) {

ch = *hexstr++;

if (ch < 0xa0) {

LcdBuffer[LcdRow][LcdCol ++] = (ch >> 4) + '0';

}

else {

LcdBuffer[LcdRow][LcdCol ++] = (ch >> 4) - 10 + 'A';

}

if ((ch & 0x0f) < 0x0a) {

LcdBuffer[LcdRow][LcdCol ++] = (ch & 0x0f) + '0';

}

else {

LcdBuffer[LcdRow][LcdCol ++] = (ch & 0x0f) - 10 + 'A';

}

}

}

UartObj::UartObj(void)

{

UartInit();

}

void UartObj::UartInit(void)

{

Start = false;//还未进行自适应

Count = 0;

PRDREG = 0;

}

unsigned int UartObj::TestBio(void)

unsigned int PortBIO = 0;//BIO引脚为低电平

asm(" bc __TestBio__,BIO");

PortBIO = 0x200;//BIO引脚为高电平(为何为0x200???以后就知道了)

asm("__TestBio__");//跳转地址

return PortBIO;

}

void UartObj::UartExec(void)

{

unsigned long timerH, timerL, timer;

bool error = true;

if (!Start) {

TIMER1->TCR |= (1 << TCR_TSS);//关闭定时器1

TIMER1->TIM = TIMER1->PRD;

TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

SREG->IFR = (1 << IFR_TINT1);//清除TINT1中断标志

while(!(SREG->IFR & (1 << IFR_TINT1))) {

if (TestBio()) {//等待BIO上跳

TIMER1->TCR |= (1 << TCR_TSS);//关闭定时器1

PRDREG = TIMER1->PRD - TIMER1->TIM;//存时间基准

timer = (unsigned long)(PRDREG);

TIMER1->TIM = TIMER1->PRD;//0xffff

TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

SREG->IFR = (1 << IFR_TINT1);//清除TINT1中断标志

timerH =0L;

while(TestBio()) {

if (SREG->IFR & (1 << IFR_TINT1)) {

TIMER1->TCR |= (1 << TCR_TSS);//关闭定时器1

timerH += 0xffff;

TIMER1->TIM = TIMER1->PRD;

TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

SREG->IFR = (1 << IFR_TINT1);//清除TINT1中断标志

if (timerH >= (6 * timer + (6 * timer * 3 / 100))) goto __error__;//高电平太宽(6.5) }

}

TIMER1->TCR |= (1 << TCR_TSS);//关闭定时器1

timerH += TIMER1->PRD - TIMER1->TIM;

TIMER1->TIM = TIMER1->PRD;//0xffff

TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

if (timerH >= (6 * timer + (6 * timer * 3 / 100))) goto __error__;//高电平太宽(6.5) if (timerH <= (6 * timer - (6 * timer * 3 / 100))) goto __error__;//高电平太宽(5.5)

timerL = 0;

while(!TestBio()) {

if (SREG->IFR & (1 << IFR_TINT1)) {

TIMER1->TCR |= (1 << TCR_TSS);//关闭定时器1

timerL += 0xffff;

TIMER1->TIM = TIMER1->PRD;

TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

SREG->IFR = (1 << IFR_TINT1);//清除TINT1中断标志

if (timerL >= (2 * timer + (2 * timer * 3 / 100))) goto __error__;//高电平太宽(2.5) }

}

TIMER1->TCR |= (1 << TCR_TSS);//关闭定时器1

timerL += TIMER1->PRD - TIMER1->TIM;

TIMER1->TIM = TIMER1->PRD;//0xffff

TIMER1->TCR &= ~(1 << TCR_TSS);//启动定时器1

if (timerL >= (2 * timer + (2 * timer * 3 / 100))) goto __error__;//高电平太宽(2.5) if (timerL <= (2 * timer - (2 * timer * 3 / 100))) goto __error__;//高电平太宽(1.5)

Start = true;

error = false;

__error__:

/*------在9600BPS下的LCD12864显示结果---------------

PRDREG= 2868

timerH= 0000F3C2

timerL= 00005124

波特率= 9615.38

--------------------------------------------------*/

Lcd.SetLcdDisplayPos(3, 0);

Lcd.LcdDisplay("波特率= ");

if (error) {

PRDREG = 0;

timerH = timerL = 0;

Lcd.LcdDisplay(" 无效 ");

}

else {

Lcd.LcdDisplay(" ");

Lcd.SetLcdDisplayPos(3, 8);

Lcd.LcdDisplay((double)(1000000 / (double)(timerH / 600)));

}

Lcd.SetLcdDisplayPos(0, 0);

Lcd.LcdDisplay("PRDREG= ");

Lcd.LcdDisplay(PRDREG);

Lcd.SetLcdDisplayPos(1, 0);

Lcd.LcdDisplay("timerH= ");

Lcd.LcdDisplay(timerH);

Lcd.SetLcdDisplayPos(2, 0);

Lcd.LcdDisplay("timerL= ");

Lcd.LcdDisplay(timerL);

SREG->IFR = (1 << IFR_TINT1);//清除TINT1中断标志 break;

}

}

}

else {

}

}

void UartObj::UartRecExec(void)

{

DDRX >>= 1;

DDRX |= TestBio();

Count ++;

if (Count >= 8) {//接收够8位数据

DDR = DDRX;

Count = 0;

SREG->IMR |= (1 << IMR_TINT0);//允许TINT0中断

}

}

int main(void)

{

Enable();//开中断

while(1)

{

if (::IOXF) {

SREG->ST1 |= (1 << ST1_XF);

}

else {

SREG->ST1 &= ~(1 << ST1_XF);

}

// idle();

}

}

interrupt void Timer0Isr() {

static int count = 0;

static unsigned int ledcount = 0;

//char str[17];

count ++;

if (count >= 500) {

count = 0;

// Lcd.SetLcdDisplayPos(0, 0);

// std::sprintf(str, "ledcount=%04X ", ledcount >> 2);//注意std:: // Lcd.LcdDisplay("ledcount=");

// Lcd.LcdDisplay(ledcount >> 2);

Lcd.LcdDisplayBuffer();//刷新LCD显示缓冲区

/*

Lcd.SetLcdDisplayPos(3, 0);

if ((ledcount & 0x03) == 0) {

Lcd.LcdDisplay("12345678");

Lcd.SetLcdDisplayPos(3, 8);

Lcd.LcdDisplay("我晕倒了");

}

else {

Lcd.LcdDisplay("你在倒塌");

Lcd.SetLcdDisplayPos(3, 8);

Lcd.LcdDisplay("87654321");

}

*/

::IOXF = !::IOXF;//郁闷~~~中断中ST1被保护~~~

ledcount ++;

}

}

interrupt void Timer1Isr() {//串口Uart的软时?

Uart.UartRecExec();

TIMER1->TCR |= (1 << TCR_TSS);//关闭启动定时器1(自毁) }

interrupt void Eint0Isr() {

Uart.UartExec();

SREG->IFR = (1 << IFR_INT0);//清除INT0中断标志

}

interrupt void Eint1Isr() {

// Lcd.SetLcdDisplayPos(2, 0);

// Lcd.LcdDisplay("欢迎INT1中断观光");

SREG->IFR = (1 << IFR_INT1);//清除INT1中断标志

}

interrupt void Eint2Isr() {

// Lcd.SetLcdDisplayPos(2, 0);

// Lcd.LcdDisplay("欢迎INT2中断观光");

SREG->IFR = (1 << IFR_INT2);//清除INT2中断标志

}

interrupt void Eint3Isr() {

// Lcd.SetLcdDisplayPos(2, 0);

// Lcd.LcdDisplay("欢迎INT3中断观光");

SREG->IFR = (1 << IFR_INT3);//清除INT3中断标志}

波特率自适应的RS-485中继器设计

麓!誊萋囊霉毫螽囊篓蔷要毫曩囊枣鼍鬟蔓一鬻薹萋j鼍雾冀簪耋薹攀羔。川篓囊萋i薹鬻波特率自遁应的RS一485中继嚣设计 ■河北理工大学张习加李成群 引言 RS一485收发器采用平衡发送和差分接收,因此具有 抑制共模干扰的能力;加上接收器具有高灵敏度,能检测 低达200mV的电压,故传输信号能在千米以外得到恢 复。使用RS一485总线,一对双绞线就能实现多站联网, 构成分布式系统,且设备简单、价格低廉,能进行长距离通 信,因而得到了广泛的应用。由于在双绞线上的电平损 耗,RS一485标准通信的最大传输距离是1200m,因此更 远距离的应用中必须使用中继器。网络节点数与所选芯 片驱动能力和接收器的输入阻抗有关。RS一485标准规 定了最大总线负载为32个单位负载,若应用中总线负载 大于32个单位负载则必须使用中继器。 1RS一485中继器原理[1’2] Rs一485是半双工方式,两线双向传送差分信号,具 有多点、双向通信能力,即允许多个发送器和接收器连接 到同一条总线上,传输线上信号的传输方向不定。因此, 识别和控制好传输线上的信号传递方向是设计RS~485 中继器的关键。 RS一485标准规定:数据信号采用差分传输方式 (differential出ivermode),也称为“平衡传输”。它使用一 对双绞线,将其中一根线定义为A,另一根线定义为B,如 图1所示。 使能 A B f痞 I稍 f瘤 I自 +6V 许电平范围 +2V A—B电平范围 一2V 许电平范围 一6V 图1RS一485发送器的示意图 通常情况下,RS一485发送器A、B之间的正电平在+2~+6V,是一种逻辑状态;负电乎在一6~一2V,是另一种逻辑状态。在RS一485发送器件中,一般有一个“使能”控制信号,用于控制发送器与传输线的切断和连接。当“使能”端为低电平时,发送器输出处于高阻状态,称作“第三态”。它是有别于逻辑“1”与“o”的第三种状态。 对于RS一485接收器,也作出与发送器相对的规定,收、发端通过平衡双绞线将A—A与B—B对应相连。当在接收端A、B之间有大于+200mV的电平时,输出为正逻辑电平;小于一2。omV时,输出为负逻辑电平。在接收器的接收平衡线上,电平范围通常为200mV~6V,如图2所示。 A B 使能 电平范围 传输电平范围 图2RS一485接收器的示意图 RS一485接收器同样定义逻辑1(正逻辑电平)为B>A的状态,逻辑o(负逻辑电平)为A>B的状态,A、B之间的压差不小于200mV。在RS~485接收器件中,一般也有一个“使能”控制信号,用于控制接收器与传输线的切断和连接。当“使能”端为高电平时,接收器与传输线切断,接收器输出为高电平;当“使能”端为低电平时,接收器输出电平与总线信号的逻辑电平一致。 RS一485中继器原理图如图3所示。正常工作时主要有三个状态:空闲状态,数据从RS一485收发器Ul边的总线往RS一485收发器U2边的总线传送(简称“数据右传状态”),数据从RS一485收发器U2边的总线往RS一485收发器U1边的总线传送(简称“数据左传状态”)。(1)空闲状态 当中继器上电启动运行或总线上没有数据传送时,中继器工作在空闲状态。RS一485收发器U1、U2均为接收数据状态,U1、U2的ENl、EN2引脚均为低电平。 (2)数据右传状态 当RS一485收发器U1边检测到连接其A、B引脚总 62《牛I;机与嵌入式系'毛应用》adv@mesnet.com.cn(广告专用) 万方数据

51单片机串口通信及波特率设置

51单片机串口通信及波特率设置 MCS-51单片机具有一个全双工的串行通信接口,能同时进行发送和接收。它可以作为UART(通用异步接收和发送器)使用,也可以作为同步的移位寄存器使用。 1. 数据缓冲寄存器SBUF SBUF是可以直接寻址的专用寄存器。物理上,它对应着两个寄存器,即一个发送寄存器一个接收寄存器,CPU写SBUF就是修改发送寄存器;读SBUF就是读接收寄存器。接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时的响应接收器的中断,没有把上一帧的数据读走而产生两帧数据重叠的问题。对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生重叠问题。 2. 状态控制寄存器SCON SCON是一个逐位定义的8位寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态,SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。它的各个位定义如下: MSB LSB SM0 SM1 SM2 REN TB8 RB8 TI RI SM0和SM1是串口的工作方式选择位,2个选择位对应4种工作方式,如下表,其中Fosc是振荡器的频率。 SM0 SM1 工作方式功能波特率 0 0 0 8位同步移位寄存器Fosc/12 0 1 1 10位UART 可变 1 0 2 11位UART Fosc/64或Fosc/32 1 1 3 11位UART 可变 SM2在工作方式2和3中是多机通信的使能位。在工作方式0中,SM2必须为0。在工作方式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。在工作方式2和3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。此功能可用于多处理机通信。 REN为允许串行接收位,由软件置位或清除。置位时允许串行接收,清除时禁止串行接收。 TB8是工作方式2和3要发送的第9位数据。在许多通信协议中该位是奇偶位,可以按需要由软件置位或清除。在多处理机通信中,该位用于表示是地址帧还是数据帧。 RB8是工作方式2和3中接收到的第9位数据(例如是奇偶位或者地址/数据标识位),在工作方式1中若SM2=0,则RB8是已接收的停止位。在工作方式0中RB8不使用。 TI 为发送中断标志位,由硬件置位,软件清除。工作方式0中在发送第8位末尾由硬件置位;在其他工作方式时,在发送停止位开始时由硬件置位。TI=1时,申请中断。CPU 响应中断后,发送下一帧数据。在任何工作方式中都必须由软件清除TI。 RI为接收中断标志位,由硬件置位,软件清除。工作方式0中在接收第8位末尾由硬件置位;在其他工作方式时,在接收停止位的中间由硬件置位。RI=1时,申请中断,要求CPU取走数据。但在工作方式1中,SM2=1且未接收到有效的停止位时,不会对RI置位。在任何工作方式中都必须由软件清除RI。 系统复位时,SCON的所有位都被清除。 控制寄存器PCON也是一个逐位定义的8位寄存器,目前仅仅有几位有定义,如下所示:MSB LSB

哈利波特与死亡圣器上中英双语台词

这是个黑暗的时候这是不可否认的 These are dark times, there is no denying. 我们的世界不会面临比今天更大的威胁 Our world has, perhaps, faced no greater threat than it does today. 不过我会对我们公民说 But I say this to our citizenry: 我们是你们每一个人的公仆… We, ever your servants... …将继续捍卫你们的自由… ...will continue to defend your liberty... …并且设法排除这股力量 ...and repel the forces that seek to take it from you. 你们的魔法部仍然… Your Ministry remains... …很强大的 ...strong. (黑暗标记引发恐慌) (暴力蔓延麻瓜家庭遇害) (食尸人数目增加) 赫敏茶好了亲爱的 Hermione. Tea's ready, darling. 来了妈妈 Coming, Mom. 快点达德利赶快 Come on, Dudley, hurry up. 我不明白干嘛非得离开这里?

I still don't understand why we have to leave. 因为继续住在这里很不安全 Because, unh, it's not safe for us here anymore. 荣恩告诉你父亲晚餐快好了 Ron, tell your father supper's nearly ready. 这是在澳大利亚吗? Is this in Australia? 看起来好极了不是吗? Looks wonderful, doesn't it? 离澳大利亚东海岸三千五百公里远 Three and a half thousand kilometers along Australia's east coast. 一忘皆空 Obliviate. 片名:《哈利波特与死神的圣物上卷》 (字幕原创:David Chiu 双语制作:dahongying) 赛佛勒斯 Severus. 我还担心你是不是迷路了… I was beginning to worry you had lost your way. 来吧我们给你留了座位 Come, we've saved you a seat. 我相信你肯定带来了什么消息吧? You bring news, I trust? 时间订在下周六晚上 It will happen Saturday next, at nightfall. 我听到的不一样我的主人

STM32单片机的串口通信波特率计算方法

STM32单片机的串口通信波特率计算方法 1. 什么是波特率 不管是什么单片机,在使用串口通信的时候,有一个非常重要的参数:波特率。什么是波特率:波特率就是每秒传送的字节数。双方在传输数据的过程中,波特率一致,这是通讯成功的基本保障。下面以STM32单片机为例,讲解一下串口波特率的计算方法。 2. STM32波特率相关的寄存器 STM32单片机设置波特率的寄存器只有一个:USART_BRR寄存器,如下图所示。 该寄存器的有效位数为16位,前4位用于存放小数部分,后12位用于存放整数部分。将波特率算出来后,数值填入这个波特率就可以了。下面介绍如何计算。 3. 波特率计算方法 STM32的数据手册给出了计算方法,有一个公式,如下图所示: 在这个公式上,共有三个变量,其中两个我们是知道的,Fck和Tx/Rx波特率这两个是已知的,USARTDIV是未知的。通过该公式的描述可以看出如果使用USART1的话,那Fck 就是PCLK2=72MHz,否则就是PCLK1=36MHz,Tx/Rx波特率这个参数是已知的。只需要计算出USARTDIV的值赋值给USART_BRR寄存器就可以了。以115200为例,将公式变形后得到:USARTDIV = 72×1000000/(16×115200) = 39.0625。即将39.0625写入USART_BRR即可。 前文说过,USART_BRR的前4位存放小数部分,后12位存放整数部分。 那小数部分DIV_Fraction = 0.0625×16 = 1 = 0x01;那整数部分DIV_Mantissa = 39 = 0x27;那USART_BRR = 0X271; 数据手册给我们提供了一张数据表: 在这张数据表上,已经算出了常用的波特率值,我们可以拿来直接用。但是如果我们想把

8051的串口波特率的计算(笔记版)

8051的串口波特率的计算 1、方式0的波特率,固定为晶振频率的十二分之一。 2、方式2的波特率,取决于PCON寄存器的SMOD位。PCON是一个特殊的寄 存器,吹了最高位SMOD位,其他位都是虚设的。计算方法如下: SMOD=0,波特率为晶振的1/64; SMOD=1,波特率为晶振的1/32. 3、方式1与方式3的波特率都是由定时器的溢出率决定的。 公式为: BR=(2SOMD/32)*(定时器TI的溢出率) 通常情况下,我们使用定时器的方式2,即比率发生器,自动重载计数常数。 溢出的周期为: T=(256-X)*12/fosc 溢出率为溢出周期的倒数,即 T1=1/T 所以: 式中:SMOD是所选的方式,fosc是晶振频率。X是初始值。 51单片机模拟串口波特率计算方法 1.计算波特率位间隔时间(即定时时间,其实就是波特率的倒数) 位间隔时间(us)=10(6)(us)/波特率(bps)

2.计算机单片机指令周期: 指令周期(us)=12/晶振频率(Mhz) 补充问题:做串口通信时,为什么要把晶振频率设为11.0592,为什么要把波特率设为9600? 先说波特率。波特率从300到115200都可以,甚至更高或更低。一般规范的波特率都是3的倍数,比如9600、19200、38400;但是并不是一定的,波特率也可以是10000或者10001、10002,只要你的设备能产生符合这个要求的频率,尤其是自己用时,波特率都是很随意的,没有限制。只是多数时候为了和电脑配合,波特率才规范为固定的几个值,且为了传输稳定,用9600。 用11.0592晶振的原因是51单片机的定时器导致的。通常用11.0592M晶振是为了得到标准的无误差的波特率。举例说来,如我们要得到的9600的波特率,晶振为11.0592M和12M,定制器1为2SMOD设为1,分别看看那所求的TH1为何值。代入公式: 11.0592M 9600=(2/32)*((11.0592M/12)(256-TH1)) TH 1=250 12M 9600=(2/32)*((12M/12)(256-TH1)) TH1=249.49

用CPLD实现串行通信时的波特率自动侦测

用CPLD实现串行通信时的波特率自动侦测 杨李莎1朱华福 2 (1.长安大学研究生部,陕西西安 710064;2.云南昆船设备有限公司昆明 650236) 摘要:本文介绍了一种利用CPLD实现波特率自动侦测的方法,文章最后给出其仿真结果关键词:串行通信波特率自动侦测复杂可编程逻辑器件 Abstract: In this paper, it introduces a way to automatically detect baud rate by using CPLD, and in the end indicates it’s emulation results . Key words: serial communication baud rate auto detected CPLD 1、引言 串行数据通信是应用极为广泛的技术,通过数据传输控制或监测中心可以对远端设备进行控制和监测设备的工作状态。串行外设都会用到RS-232C 异步串行接口.传统上采用专用的集成电路即UART实现,如TI、EXAR、EPIC 的550、452等系列,但是我们一般不需要使用完整的UART的功能,而且对于多串口的设备或需要加密通讯的场合使用UART也不是最合适的。如今的许多的电器都有串口,主要用于软件的升级或者用于自诊断。通常单机设备的串行通信波特率设置都是采用硬件拨码的方式进行的,对于一些拨码开关特别多的设备来说难于记忆,因此能否寻求一种波特率自适应的方法来解决这个问题呢?回答是肯定的,本文就介绍一种用复杂可编程逻辑器件来实现波特率自动侦测的方法。系统只设计了数据接收模块,利用VHDL语言对其进行编程,最后给出其仿真结果。 2、系统设计 2.1系统介绍 图1所示为数据接收模块结构框图,数据接收模块由波特率发生基准时钟、开始位下降沿检测、接收控制、串并转换器、锁存器、缓冲器等部分组成。为了能准确地侦测出接收数据的波特率,数据接收模块中采用了波特率发生基准时钟,首先用基准时钟对RXD端的数据进行接收采样,然后按波特率自动侦测原理进行波特率自动侦测,最后产生一个与发送端发送的数据相同的波特率,利用波特率进行通信。 1【作者简介】杨李莎(1981—)女,长安大学研究生部04级交通信息工程及控制专业硕士研究生,主要从事高速公路和城市道路的交通控制及管理研究。

波特率计算

波特率选择 在串行通讯中,收发双方的数据传送率(波特率)要有一定的约定。在8051串行口的四种工作方式中,方式0和2的波特率是固定的,而方式1和3的波特率是可变的,由定时器T1的溢出率控制。 方式0 方式0的波特率固定为主振频率的1/12。 方式2 方式2的波特率由PCON 中的选择位SMOD 来决定,可由下式表示: 波特率=2的SMOD 次方除以64再乘一个fosc,也就是当SMOD=1时,波特率为1/32fosc,当SMOD=0时,波特率为1/64fosc 3.方式1和方式3 定时器T1作为波特率发生器,其公式如下: 波特率=定时器T1溢出率 产生溢出所需的周期数/计数率T 132 2=溢出率T 1mod ?s 式中T1计数率取决于它工作在定时器状态还是计数器状态。当工作于定时器状态时,T1计数率为fosc/12;当工作于计数器状态时,T1计数率为外部输入频率,此频率应小于fosc/24。产生溢出所需周期与定时器T1的工作方式、T1的预置值有关。 定时器T1工作于方式0:溢出所需周期数=8192-x 定时器T1工作于方式1:溢出所需周期数=65536-x 定时器T1工作于方式2:溢出所需周期数=256-x 因为方式2为自动重装入初值的8位定时器/计数器模式,所以用它来做波特率发生器最恰当。 当时钟频率选用11.0592MHZ 时,取易获得标准的波特率,所以很多单片机系统选用这个看起来“怪”的晶振就是这个道理。 下表列出了定时器T1工作于方式2常用波特率及初值。 常用波特率 Fosc(MHZ) SMOD TH1初值 19200 11.0592 1 FDH 9600 11.0592 0 FDH 4800 11.0592 0 FAH 2400 11.0592 0 F4h 1200 11.0592 0 E8h 例如9600 11.0592 0 FDH 溢出率T 1定时时32 2 =波特率mod ?s T1溢出率= T1计数率/产生溢出所需的周期数 产生溢出所需的周期数=256-FD(253)=3 SMOD=0 11059200/12*3 *1/32=9600

单片机波特率的计算方法

51单片机波特率计算的公式和方法 51单片机芯片的串口可以工作在几个不同的工作模式下,其工作模式的设置就是使用SCON寄存器。它的各个位的具体定义如下: SM0SM1SM2REN TB8RB8TI RI SM0、SM1为串行口工作模式设置位,这样两位可以对应进行四种模式的设置。串行口工作模式设置。 波特率在使用串口做通讯时,一个很重要的参数就是波特率,只有上下位机的波特率一样时才可以进行正常通讯。波特率是指串行端口每秒内可以传输的波特位数。这里所指的波特率,如标准9600不是每秒种可以传送9600个字节,而是指每秒可以传送9600个二进位,而一个字节要8个二进位,如用串口模式1来传输那么加上起始位和停止位,每个数据字节就要占用10个二进位,9600波特率用模式1传输时,每秒传输的字节数是9600÷10=960字节。 51芯片的串口工作模式0的波特率是固定的,为fosc/12,以一个12M的晶振来计算,那么它的波特率可以达到1M。模式2的波特率是固定在fosc/64或fosc/32,具体用那一种就取决于PCON寄存器中的SMOD位,如SMOD为0,波特率为focs/64,SMOD为1,波特率为focs/32。 模式1和模式3的波特率是可变的,取决于定时器1或2(52芯片)的溢出速率,就是说定时器1每溢出一次,串口发送一次数据。那么我们怎么去计算这两个模式的波特率设置时相关的寄存器的值呢?可以用以下的公式去计算。

上式中如设置了PCON寄存器中的SMOD位为1时就可以把波特率提升2倍。通常会使用定时器1工作在定时器工作模式2下,这时定时值中的TL1做为计数,TH1做为自动重装值,这个定时模式下,定时器溢出后,TH1的值会自动装载到TL1,再次开始计数,这样可以不用软件去干预,使得定时更准确。在这个定时模式2下定时器1溢出速率的计算公式如下: 溢出速率=(计数速率)/(256-TH1初值) 溢出速率=fosc/[12*(256-TH1初值)] 上式中的“计数速率”与所使用的晶体振荡器频率有关,在51芯片中定时器启动后会在每一个机器周期使定时寄存器TH的值增加一,一个机器周期等于十二个振荡周期,所以可以得知51芯片的计数速率为晶体振荡器频率的1/12,一个12M的晶振用在51芯片上,那么51的计数速率就为1M。通常用11.0592M 晶体是为了得到标准的无误差的波特率,那么为何呢?计算一下就知道了。如我们要得到9600的波特率,晶振为11.0592M和12M,定时器1为模式2,SMOD 设为1,分别看看那所要求的TH1为何值。代入公式: 11.0592M 9600=(2÷32)×((11.0592M/12)/(256-TH1)) TH1=250

MCS-51单片机串行口工作方式与波特率计算举例

MCS-51单片机串行口工作方式与波特率计算举例 1)方式0 方式0是外接串行移位寄存器方式。工作时,数据从RXD串行地输入/输出,TXD 输出移位脉冲,使外部的移位寄存器移位。波特率固定为fosc/12(即,TXD每机器周期输出一个同位脉冲时,RXD接收或发送一位数据)。每当发送或接收完一个字节,硬件置TI=1或RI=1,申请中断,但必须用软件清除中断标志。 实际应用在串行I/O口与并行I/O口之间的转换。 2)方式1 方式1是点对点的通信方式。8位异步串行通信口,TXD为发送端,RXD为 接收端。一帧为10位,1位起始位、8位数据位(先低后高)、1位停止位。波特率由T1或T2的溢出率确定。 在发送或接收到一帧数据后,硬件置TI=1或RI=1,向CPU申请中断;但必须用软件清除中断标志,否则,下一帧数据无法发送或接收。 (1)发送:CPU执行一条写SBUF指令,启动了串行口发送,同时将1写入 输出移位寄存器的第9位。发送起始位后,在每个移位脉冲的作用下,输出移位寄存器右移一位,左边移入0,在数据最高位移到输出位时,原写入的第9位1的左边全是0,检测电路检测到这一条件后,使控制电路作最后一次移位,/SEND 和DATA无效,发送停止位,一帧结束,置TI=1。 (2)接收:REN=1后,允许接收。接收器以所选波特率的16倍速率采样RXD 端电平,当检测到一个负跳变时,启动接收器,同时把1FFH写入输入移位寄存器(9位)。由于接、发双方时钟频率有少许误差,为此接收控制器把一位传送时间16等分采样RXD,以其中7、8、9三次采样中至少2次相同的值为接收值。接收位从移位寄存器右边进入,1左移出,当最左边是起始位0时,说明已接收8位数据,再作最后一次移位,接收停止位。此后: A、若RI=0、SM2=0,则8位数据装入SBUF,停止位入RB8,置RI=1。

波特率自适应

波特率自适应方案 一、波特率自适应概念 电表检测PC 机通信的波特率,并自动匹配通信。 二、方案 1、 点对点自适应通信,即PC 机与单一电表进行自适应通信。 如果我们想利用PC 机(波特率为1200bps )对未知波特率的电表通信,则需要进行下面几个步骤。 1.1 第一步:PC 机需要以1200bps 发送“ 55H 55H ” 1.2 第二步:等待未知波特率的电表应答。如果自适应成功则应答字符为:“80H ”,这时未知波特率的电表将更波特率为1200bps 。如果无应答,应答字符有误,或者在500ms 内未应答则此次自适应过程失败。重复第一步和第二步,重复三次都未应答则自适应失败。 1.3 第三步:成功自适应则可以利用1200bps 对电表进行通信。自适应失败只能将电表的波特率修改成1200bps 才能通信。 如果想用其他的波特率通信,请重复上面步骤 流程图 PC (1200)发送5555H → 电表回复80H → 1200正常通讯 →若要修改波特率 ↑ ↓ ← 电表未回复80H 2、 点对多自适应通信,即广播方式让总线上的电表统一波特率 流程图 3、 电表单片机自适应波特率原理 在不同波特率下发送一位数据的时间是不一样的,利用这个原理,确认在1200、2400、4800、9600状态下发送一个字节所需要的时间段B1、B2、B3、B4,将其存储到单片机中。 PC 机以广播方式1200bps 发送5555H 等待500ms 再次广播 发送55H 等待500m PC 机以 1200bps 抄读系统表

当PC机发送数据到电表时,单片机利用定时器测量接收一个字节的时间A,然后将A与B1,B2,B3,B4进行比对,假如A在B1范围内,那么单片机将电表波特率设置为1200,修改波特率结束。 流程图如下所示: 广播或者PC发送5555H(1200波特率) 单片机接收到第一个字节数据 55H,产生接收中断1 定时器开始工作,每产生一次定 时器中断就对变量A进行累加 单片机接收到第二个字节数据 55H,产生接收中断2 关闭定时器,将变量A与 B1/B2/B3/B4进行比对,确认A 属于范围B1 单片机将电表波特率改为1200 波特率修改成功

基于51单片机的波特率自动识别系统程序

#include #define uint unsigned int #define uchar unsigned char #define disp_off 0x3e //关显示 #define disp_on 0x3f //开显示 #define disp_x 0xb8 //页地址 #define disp_z 0xc0 //行地址 #define disp_y 0x40 //列地址 #define comm 0 //命令标志 #define dat 1 //数据标志 #define data_ora P0 //MCU P0<------> LCM sbit cs1=P2^0; //cs1=L,选择左半屏 sbit cs2=P2^1; //cs2=L,选择右半屏 sbit rs =P2^2; //H:写数据,L:写指令 sbit rw =P2^3; //H:读,L:写 sbit e =P2^4; //读写使能 sbit bf =P0^7; //执行操作标志 sbit res=P0^4; //复位初始化标志 uchar uart_data,temp,baud_set=0x00; uchar dispnum[90]; uchar baud[5]={0x00,0x09,0x06,0x00,0x00}; uchar r_dat[4]={0x00,0x10,0x00,0x00}; uchar code baudrate[7][5]={ {0x00,0x00,0x03,0x00,0x00}, {0x00,0x00,0x06,0x00,0x00}, {0x00,0x01,0x02,0x00,0x00}, {0x00,0x02,0x04,0x00,0x00}, {0x00,0x04,0x08,0x00,0x00}, {0x00,0x09,0x06,0x00,0x00}, {0x01,0x04,0x04,0x00,0x00}, }; //波特率大小 uchar code hz11[]={ /*-- 隶书12; 此字体下对应的点阵为:宽x高=16x16 --*/ /*-- 文字: 发--*/ 0x00,0x00,0x00,0xE0,0xA0,0x80,0x80,0xF0, 0x80,0xA0,0xB0,0x80,0x00,0x00,0x00,0x00, 0x00,0x08,0x08,0x08,0x1C,0x14,0x13,0x1B, 0x0D,0x07,0x0B,0x18,0x18,0x30,0x10,0x00, /*-- 文字: 送--*/

单片机与PC机串行通信中波特率的确定

单片机与PC机串行通信中波特率的确定 关键字:单片机 PC机串行通信波特率 1 单片机异步通信口的特点及波特率的选定 MSC51系列单片机有一个全双工的异步通信口,他利用其RXD和TXD与外界进行通信,其内部有2个物理上完全独立的接收、发送缓冲器SBUF,可同时发送和接收数据。异步串行通信发送和接收数据的速率与移位脉冲同步。一般用51系列的T1定时器作为波特率发生器,T1的溢出率经二分频(或不分频)后又经十六分频作为串行发送或接收的移位脉冲,移位脉冲的速率即波特率。单片机的异步通信波特率与串行口的工作方式、主振频率Fosc及定时器T1的工作方式有关。一般通信中使T1工作于方式2(可重装时间常数方式),若Fosc取6 MHz,则波特率的计算公式如下: 其中:SMOD是可编程的(即PCON的第8位),由此公式计算出的波特率是不标准的波特率。? 2 PC机异步通信口及其波特率的设置 由于UART(通用异步接收/发送器)的产品型号很多,PC机和XT机都采用的是INS8250芯片, AT机采用的是NSI16450芯片,他们二者是兼容的。因此这里以8250芯片为例来说明PC机异步通信波特率的设定方法。PC机中有2个异步通信口,一个是COM1,其端口地址范围是3F8H~3 FFH,另一个是COM2,其端口地址是2F8H~2FFH。其与MODEM配合可以实现远距离通信。其波特率是标准波特率50~9 600 b/s。 8250内部有10个寄存器端口,其中有一个除数锁存器,可以通过编程除数的大小来确定异步通信的波特率。8250使用的频率是1843 2 MHz的基准时钟输入信号,所以必须用分频的方法产生所需要的波特率(移位脉冲)。除数锁存器的值必须在8250初始化时设置,即把通信线路控制器的最高位(DLAB)置1,然后分两次把除数锁存器的高8位和低8位分别写入端口地址3F8H和3F9H(COM1),8250传送或接收串行数据时使用的时钟信号的频率是数据传输波特率的16倍,即波特率=16×除数/1 843 200。由此公式可以计算出几种标准波特率与除数的对应值如下:对应于波特率为1 200 b/s的除数锁存器的低8位值为60H;对应于波特率为2 400 b/s的除数锁存器低8位的值为30H;对应于波特率为4 800 b/s的除数锁存器低8位的值为18H;对应于波特率为9 600 b/s的除数锁存器低8位的值为0CH。 3 用PC机的汇编语言设计的串行通信程序中波特率的设定 PC机的ROM BIOS串行通信管理程序为14H号中断处理程序,他可支持DTE与DCE间的通信,也能支持两个DTE间用MODEM连接方式的RS232C接口通信。BIOS串行通信管理程序的功能是:串行口初始化、发送数据字符、接收数据字符和取串行口状态。他是利用查询方式来实现数据字符的接收和发送,但当查询超时一定时间后就不再继续查询,而认为是线路故障或对方未准备好,并通过返回参数中的超时标志来表示操作失败。 BIOS INT 14H的中断功能调用的入口和出口参数如下: 例如要设计用COM1来发送字符,波特率为1200 b/s,8 个数据位,1个停止位,采用查询方式无效验位,则初始化程序如下: 4 利用Turbo C编写的PC机通信程序中波特率的设定 Turbo C函数库中提供了专门的调用BIOS串行软中断的函数Bioscom(int cmd,char byte,int pure),其中:参数cmd用来设置通信类型,cmd=0,初始化串行口pure;cmd=1,发送一个字符;cmd=2,接收一个字符;cmd=3返回串口当前状态。参数byte用来确定串行口的异步

52单片机串口波特率设置函数

52单片机串口波特率设置函数 波特率设置太麻烦了吧,用函数设置吧,不必东奔西走的找了,个人自己写的代码,欢迎使用,不需要金币,好用就评价一下吧 注意了,仅用于52系列单片机,代码如下: /*----------52单片机波特率设置函数-------------- ------------------------------------------------ 作者:wenguang.li Email:liwg@https://www.doczj.com/doc/087381967.html,//wenguang.li@https://www.doczj.com/doc/087381967.html, MCU: *52 Cristal frequency unit MHz 晶体频率单位MHz Baudrate as you desired Example: set52_baudrate(11.0592,57600) Use Timer2 使用定时器2 ------------------------------------------------ ----------------------------------------------*/ //if osc=11.0592M //can set baudrate 110,300,600,1200,2400,4800,9600,19200,38400,57600,115200bps void set52_baudrate(float frequency,long int baudrate) { unsigned int itmp; unsigned char tlow,thigh; itmp=(int)(65536-(frequency*1000000)/(baudrate*32)); thigh=itmp/256; tlow=itmp%256; SCON=0x56; T2CON=0x30; RCAP2H=thigh; RCAP2L=tlow; TH2=thigh; TL2=tlow; TR2=1; //set ok } /////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////

哈利波特读后感大全

哈利波特读后感大全 篇一:哈利波特读后感机智勇敢和完善的判断能力只是一个人才的最开始! ——题记 《哈利波特》全集讲述了一个男孩读小学,并坚持消灭坏人“神秘人”的事情。《魔法石》讲的就是刚入学的哈利在学校学习魔法,与同学相处和与“神秘人”的第一次战斗。书中的几个主人公有哈利积极向上的同学赫敏,憨厚的罗恩,自高自傲的马尓福,霍格沃兹的校长邓不利多,管理员海格,“神秘人”伏地魔,机智勇敢的哈利波特等。都给我留下了深刻的印象。 本书作者罗琳的创作灵感于她24岁那年在火车上见到一个穿着黑色长袍的小巫师。罗琳把一些神奇的,在现实生活中不可能发生的东西加入了书中。如去霍格沃兹的9 又3/4站台,飞天扫帚,可以传送人的火焰杯。生长于英国的她也将一些英国,欧美地区的思想、风俗编入了书中。就比如英国人非常注重花语,也就是花的含义。当植物老师斯内普第一次见到哈利时,问他“如果把水仙根粉末加入艾草浸液会怎样?”这看似只是个学术问题,只是斯内普的一个刁难,但其实从不同花语来看,这是一句道歉——水仙是百合的一种,英文为Lil,它的花语是“我的悔恨追随你至坟墓。”而艾草的意思是“缺席”。斯内普的这句话实际是“我对Lil

的死非常悔恨。”Lil就是哈利波特的母亲,她在对战伏地魔时不幸去世。不仅这一处,罗琳还将黑猫、女巫、数字13、黑色星期五等传说,俗记都加入了书中。 书中的主人公哈利波特是一个机智勇敢的男孩。由于父母都被伏地魔杀死,他从小生长于姨妈家。姨妈一家并不友善,这段生活使哈利学会了坚强、独立、坚持自我。在霍格沃兹偶然发现可以看到自己欲望的厄里斯魔镜,在沉湎于其中,不能自拔时,在校长劝阻下远离了魔镜,回归了现实生活使他明白了“沉湎于虚幻的梦想而忘记现实是毫无益处的。”字穿越了活门板,为了魔法石与奇洛和伏地魔大战时,他发现真正替黑魔法效忠的不是对他十分苛刻的斯内普教授,而是看似可怜的洛奇。这使我明白了评定一个人不应该仅从外表来决断。像好人的不一定善良,有时只是一种掩盖。而看似坏人的,有时只是不善于表达而被误会。哈利在经历过此事后大概会提高判断能力了吧!哈利之所以敢大胆怀疑斯内普教授,还有一个原因就是他敢于面对一切危险以及别人根本不敢想的灾难。在霍格沃兹只有哈利、赫敏与邓不利多三人敢于直呼伏地魔。其他人只要一听到这个名字便会不寒而栗。如果恶魔伏地魔卷土重来,那的确是一场灾难,哈利也意识到了严重性。但无论我们称他为“神秘人”或“伏地魔”,有朝一日,他都会为夺回政权而回来。所以哈利敢于挑战一切危险的勇气很值得赞扬。

51单片机晶振与波特率的关系

51 单片机晶振与波特率的关系 在串行通信中, MCS — 51 串口可约定四种工作方式。其中,方式 0 和方式 2 的波特率是固定的,而方式 1 和方式 3 的波特率是可变的,由定时器 T1 的溢出率决定。波特率是指串行端口每秒内可以传输的波特位数。这里所指的波特率,如标准9600 不是每秒种可以传送 9600 个字节,而是指每秒可以传送9600 个二进位,而一个字节要 8 个二进位,如用串口模式 1 来传输,那么加上起始位和停止位,每个数据字节就要占用 10 个二进位, 9600 波特率用模式 1 传输时,每秒传输的字节数是9600 - 10=960字节。一、方式0 和方式 2的波特率 方式0的波特率是固定的,为fosc/12 ,以一个12M的晶振来计算,那么它的波特率可以达到 1M。 方式2的波特率是固定在fosc/64或fosc/32,具体用那一种就取决于 PCON 寄存器中的 SMOD 位,如 SMOD 为 0,波特率为 focs/64,SMOD 为 1 ,波特率为 focs/32 。二、方式 1 和方式3 的波特率 模式 1 和模式 3 的波特率是可变的,取决于定时器 1 或 2(对于 52 芯片)的溢出速率,就是说定时器 1 每溢出一次,串口 发送一次数据。可以用以下的公式去计算:上式中如设置了 PCON 寄存器中的 SMOD 位为 1 时就可以把波特率提升 2 倍。通常会使用定时器 1工作在定时器工作模式 2 下,这时定时值中的 TL1

做为计数, TH1 做为自动重装值,这个定时模式下,定时器溢出后, TH1 的值会自动装载到 TL1 ,再次开始计数,这样可以不用软件去干预,使得定时更准确。在这个定时模式 2 下定时器 1 溢出速率的计算公式如下:溢出速率 =(计数速率 )/(256-TH1 初值 ) 溢出速率 =fosc/[12*(256-TH1 初值 )] 上式中的“计数速率”与所使用的晶体振荡器频率有关,在 51 芯片中定时器启动后会在每一个机器周期使定时寄存器 TH 的值加 1,一个机器周期等于十二个振荡周期,所以可以得知 51 芯片的计数速率为晶体振荡器频率的 1/12 ,一个 12M 的晶振用在 51 芯片上,那么 51 的计数速率就为 1M 。通常用 11.0592M 晶体是为了得到标准的无误差的波特率,那么为何呢?计算一下就知道了。如我们要得到 9600 的波特率,晶振为 11.0592M 和 12M ,定时器1 为模式 2,SMOD 设为 1 ,分别看看那所要求的 TH1 为何值。代入公式: 11.0592M : 9600=(2 + 32) X ((11.0592M/12)/(256-TH1)) TH1=250 12M : 9600=(2 + 32) X ((12M/12)/(256-TH1)) TH1? 249.49 上面的计算可以看出使用 12M 晶体的时候计算出来的 TH1 不为整数,而 TH1 的值只能取整数,这样它就会有一定的误差存在不能产生精确的 9600 波特率。当然一定的误差是可以在使用中被接受的,就算使用 11.0592M 的晶体振荡器也会因晶体本身所存在的误差使波特率产生误差,但晶体本身的误差对

单片机波特率自适应

单片机从机的波特率自适应设置 一、硬件原理图 说明:DB9接到PC机的串口上。晶体震荡器可以用诸如11.0592MHz,14.7456MHz,对本文的介绍没有影响等等。这里,单片机为机为,PC机为主机。 二、自动设置理论原理 AT89C52的串行口有4种工作方式,方式1、3最常用。T2的波特率发生方式类似于常数自动重装入方式。用X16代替(RCAP2H,RCAP2L),则串行口方式1、3的波特率公式为: 波特率=fosc/[32 x (65536-X16 )]..……………………..……..…(A) 由(A)可得,单片机每接收1bit需要的时间为 接受1bit的时间=[32 x (65536- X16 )]/ fosc……………………(B) 单片机A T89C52为12分频指令系统,所以其机器周期为: 机器周期= 12/fosc……………………………………….….….……(C ) 我们可以很容易得到单片机接收1bit所需要的机器周期,假定为NUM,则由(B),(C)得NUM x 12/ fosc=[32 x (65536- X16)]/ fosc…………………………...(D) 由(D)可得,波特率定时时间常数为: X16=NUM x 3/8……………………………….…………………….….(E) 由此,关键需要得到单片机接受1 bit的机器周期数NUM。 三、自动检测主机信息的方法 不失一般性,假定串行通讯的字符协议为1起始位,8数据位,无奇偶校验位,1停止位,如下(图2)所示,

由定时器2工作原理(图3)知道,C/T2=0,TR2=0,则其加1计数,其计数速率为fosc/12,每加1需要的时间等于12/fosc,刚好就是一个机器周期。所以,只要我们在传输数据的某位开始处启动定时器,在传输该位结束时停止计数器,然后获取该范围的计数值,就是我们上面公式(E)中的NUM。 (定时器2工作原理,图3) 由图2知,如果主机(PC机)发给单片机01H(十六进制),则单片机P3.0接收数据如下波形(图4)。起始位开始时,启动定时器T2,当高电平来到时,关闭定时器T2,则计数值就等于NUM。 四、软件实现 1.流程图 这里给出获取定时常数的流程图,按主机发0x01来设计的 获取8bit数据的定时计数值(图5)计算定时时间常数(图6)

《哈利波特》读后感(精选12篇)

《哈利波特》读后感(精选12篇) 《哈利波特》读后感 读完一本经典名著后,大家心中一定有很多感想,不妨坐下来好好写写读后感吧。为了让您不再为写读后感头疼,以下是收集整理的《哈利波特》读后感,仅供参考,希望能够帮助到大家。 《哈利波特》读后感1 徜徉于书海之中,总有那一两本名作获得我的钟爱。但每当我触碰到那一本书,我会为它迷醉,为它感动,把它看了千万遍,牢牢记在了心中。以至于一念一个咒语,它就会浮现脑海,久久不能散去……拿起魔杖,念出熟悉的咒语,它便出现,与我同在——这就是JK罗琳在咖啡馆里用小纸片写成的著作,风靡世界的《哈利波特》。 虚幻的事物在罗琳的笔下变成了真实。有巫师,有精灵,也有恶魔。他们分别代表着善与恶。而这个善良的男孩——哈利波特,是这个故事的主角,他是一个注定不平凡的人。一出生便拥有了与强大黑魔法师伏地魔作斗争的标志——一道形如闪电的疤痕。那是一道非常厉害的咒语余痕,妈妈的爱把他的死亡换成了那道疤。在他11岁生日那天,发生了一件大事,由此改变了他的命运。海格给他送去了一封霍格沃茨魔法学院的录取信,告诉他身世。他很高兴地入了学,但他不知道前面的道路是多么坎坷。年仅11岁的哈利就与被伏地魔附身的奇洛教授展开了搏斗,保护了尼可洛美的魔法石;密室中勇敢战胜了少年伏地魔汤姆里德尔和蛇怪,救出了金妮;阿兹卡班中帮助了

他的教父小天狼星布莱克,还了他的清白,并借机救了无辜受罚的巴克比克;三强争霸赛中与伏地魔的对决;神秘事物司的激烈搏斗;阿不思邓布利多校长的逝世……直到哈利17岁彻底打败了伏地魔,为人们赢得了一个和平的世界。 《哈利波特》系列中我最痛恨的人就是伏地魔了,同时也为他感到惋惜。他既相貌英俊,又法力高强,为什么却比不过哈利?因为他不懂爱,不懂爱是世界上最强大的武器,只知道用高超的法术去杀害别人、威逼别人,而不是用爱心征服别人。正是爱,哈利的母亲献出了生命,使哈利得到了强大的保护,使伏地魔想尽一切办法都杀不了哈利;正是爱,哈利和他的朋友们面对恶势力能同心协力不离不弃,用他们有限的力量,一次又一次地逃过劫难;正是爱,使得所有正义的巫师联合起来,众志成城,战胜敌人……是啊!邪恶怎么可能战胜正义,战胜爱呢?佛地魔的失败是理所当然的。 福楼拜曾说过:“对不幸的命运越是抱怨,越是觉得痛苦;越是想要逃避,越是觉得恐惧。不如去面对它,迎战它、克服它,使一切痛苦称臣,使灿烂的花朵盛开在艰苦耕耘过的土地上。”哈利波特正是这样,他面对困难不低头,挺起胸膛勇敢地去面对,征服他。山中没有笔直的路,然而,有弯曲,才有雄壮、秀美;有起伏,才有波澜。正如溪流有阻碍,有不平,才有歌声!我们的道路不是平坦的,是有起伏、坑坑洼洼的。但我们不能向困难低头,要像哈利波特一样,做一个勇敢、不轻言放弃的人。 《哈利波特》读后感2

相关主题
文本预览
相关文档 最新文档