您的位置:首页 > 其它

at91sam7x256之串口uart0设置之二

2010-06-08 11:59 337 查看
搞了两天,at91sam7x256之串口uart0终于搞定了,

一开始出现的问题是发送出来的数据不对,但是用串口调试助手给开发板发送数据,然后直接回送没有问题。

原因是串口波特率设置不对,我把晶振频率FOSC作为系统主时钟MCK用了,虽然检查半天控制寄存器US_CR和模式寄存器US_MR各个位的值设置都没有问题,也是不行的。

看了开发板例程中的board .h头文件,我才知道原来晶振频率FOSC作为系统主时钟MCK不同:

#define AT91B_MAIN_OSC 18432000 // Main Oscillator MAINCK
#define AT91B_MCK ((18432000*73/14)/2) // Output PLL Clock

波特率问题就这样搞定了,可是还是有问题:

发送0x55,串口调试助手收到0xaa
发送0xbb,串口调试助手受到0xdd
这个问题也是灵机一动,这么有规律的错误,肯定是那个寄存器设置有点问题,

原来我把US_MR中US_MSBF设置了【高位在前地位在后】的发送,去掉这个US_MSBF设置使用默认的【低位在前高位在后】就可以了。

又解决一个问题,下功夫,就有收获啊。

代码都好了,贴出来以后还能用。

//UART0.H文件内容

extern AT91S_AIC * pAIC;
void SendChar(unsigned char CH);
void Init_UART0();

//UART0.C文件内容

#include <AT91SAM7X256.H>
#include "UART0.H"
#define Fosc 18432000
#define AT91B_MAIN_OSC 18432000 // Main Oscillator MAINCK
#define AT91B_MCK ((18432000*73/14)/2) // Output PLL Clock
AT91PS_PIO GPIO_A=AT91C_BASE_PIOA;
AT91PS_USART UART0 =AT91C_BASE_US0;
//----------------------------------------
AT91S_AIC * pAIC=AT91C_BASE_AIC;
unsigned char DacContralBuff[16];
//----------------------------------------
void SendChar(unsigned char CH)
{
while(!(UART0->US_CSR&0X02));
UART0->US_THR=CH;
}
//----------------------------------------
unsigned char GetChar()
{
unsigned char ch;

return ch;
}
//-----------------------------------------
__irq void Usart0ISR(void)
{
*AT91C_AIC_ICCR|=(1 << AT91C_ID_US0);
if(UART0->US_CSR&0X01)
{
DacContralBuff[0]=UART0->US_RHR&0xff;
SendChar(DacContralBuff[0]);
}
*AT91C_AIC_EOICR = 0X00;
}
//=================
__inline unsigned int AT91F_US_Baudrate (
const unsigned int main_clock, // /arg peripheral clock
const unsigned int baud_rate) // /arg UART baudrate
{
unsigned int baud_value = ((main_clock*10)/(baud_rate * 16));
if ((baud_value % 10) >= 5)
baud_value = (baud_value / 10) + 1;
else
baud_value /= 10;
return baud_value;
}

//*----------------------------------------------------------------------------
//* /fn AT91F_US_SetBaudrate
//* /brief Set the baudrate according to the CPU clock
//*----------------------------------------------------------------------------
__inline void AT91F_US_SetBaudrate (
AT91PS_USART pUSART, // /arg pointer to a USART controller
unsigned int mainClock, // /arg peripheral clock
unsigned int speed) // /arg UART baudrate
{
//* Define the baud rate divisor register
pUSART->US_BRGR = AT91F_US_Baudrate(mainClock, speed);
}

//*----------------------------------------------------------------------------
//* /fn AT91F_US_SetTimeguard
//* /brief Set USART timeguard
//*----------------------------------------------------------------------------
__inline void AT91F_US_SetTimeguard (
AT91PS_USART pUSART, // /arg pointer to a USART controller
unsigned int timeguard) // /arg timeguard value
{
//* Write the Timeguard Register
pUSART->US_TTGR = timeguard ;
}
//=================
void Init_UART0()
{
unsigned int temp=0;
GPIO_A->PIO_PER =0XfFFFFFFF;
GPIO_A->PIO_OER=0X03;//PA0,PA1设置为输出
GPIO_A->PIO_SODR =0X03; //设置为高
*AT91C_PMC_PCER = (unsigned int)1<<AT91C_ID_US0; //允许US0口的时钟
GPIO_A->PIO_PDR =0x03; //设为外设
GPIO_A->PIO_ASR =0X03; //设为外设A

UART0->US_CR|= AT91C_US_RSTRX | /* Reset Receiver */
AT91C_US_RSTTX | /* Reset Transmitter */
AT91C_US_RXDIS | /* Receiver Disable */
AT91C_US_TXDIS; /* Transmitter Disable */

// UART0->US_MR=0X108C0; //主时钟,8位数据,一位停止位,无校验 ,高位在前,异步模式
UART0->US_MR=AT91C_US_USMODE_NORMAL | /* Normal Mode */
AT91C_US_CLKS_CLOCK | /* Clock = MCK */
AT91C_US_CHRL_8_BITS | /* 8-bit Data */
AT91C_US_PAR_NONE | /* No Parity *///OVER=1 溢出错误
AT91C_US_NBSTOP_1_BIT ;
//|AT91C_US_MSBF; /* 1 Stop Bit */ //SYNC=0异步 SYNC=1同步
//异步模式 波特率=MCK/16/BRD或MCK/8/BRD;同步为波特率=MCK/BRD
UART0->US_BRGR=AT91F_US_Baudrate(AT91B_MCK,9600);// (Fosc/(9600*16)); //AT91B_MCK
// UART0->US_BRGR|=Fosc/(9600*16)<<8;
UART0->US_CR=0X50;
UART0->US_CR |= AT91C_US_RXEN | /* Receiver Enable */
AT91C_US_TXEN; /* Transmitter Enable */

//UART0->US_IDR=0;
//UART0->US_CSR//通道状态寄存器 2-发送状态,1-接收状态
/* Setup Usart Interrupt Mode and Vector with Priority 7 and Enable it */
// pAIC->AIC_SMR[AT91C_ID_US1] = 5;//设置触发模式和优先级7等级最高
pAIC->AIC_SMR[AT91C_ID_US0] = 6; //双串口中断方式接收数据需设优先级
UART0->US_IER =AT91C_US_RXRDY; //接收中断使能
// pUSART1->US_IER =AT91C_US_RXRDY;
pAIC->AIC_SVR[AT91C_ID_US0] = (unsigned long) Usart0ISR;//串口0中断地址放入向量表
// pAIC->AIC_SVR[AT91C_ID_US1] = (unsigned long) Usart1ISR;//串口1中断地址放入向量表
pAIC->AIC_IECR |=(1 << AT91C_ID_US0)|(1 << AT91C_ID_US1);//串口中断使能
UART0->US_IER=0X01; //接受中断使能

}

//main。c文件内容

#include <AT91SAM7X256.H>
#include "UART0.H"

#define LED1 (1<<18)
#define LED2 (1<<20)
#define LED3 (1<<22)
#define LED4 (1<<24)
#define Key1 (1<<19)
#define Key2 (1<<21)
#define Key3 (1<<23)
#define Key4 (1<<25)

AT91PS_PIO GPIO_B=AT91C_BASE_PIOB;

void delay(unsigned long msec)
{
while(msec--);
}
void LED_Display()
{
GPIO_B->PIO_SODR|=LED1;
delay(0xffff);
GPIO_B->PIO_SODR|=LED2;
delay(0xffff);
GPIO_B->PIO_SODR|=LED3;
delay(0xffff);
GPIO_B->PIO_SODR|=LED4;
delay(0xffff);
GPIO_B->PIO_CODR|=LED1;
delay(0xffff);
GPIO_B->PIO_CODR|=LED2;
delay(0xffff);
GPIO_B->PIO_CODR|=LED3;
delay(0xffff);
// GPIO_B->PIO_CODR|=LED4;
delay(0xffff);
}
/****************************************************************************
* 文件名:Init_GPIO()
* 功 能:初始化GPIO
*
* 说 明:
****************************************************************************/
void Init_GPIO()
{
GPIO_B->PIO_OER|=LED1;
GPIO_B->PIO_OER|=LED2;
GPIO_B->PIO_OER|=LED3;
GPIO_B->PIO_OER|=LED4;
GPIO_B->PIO_OER=0x7fffffff;
GPIO_B->PIO_SODR=0x7fffffff;
*AT91C_PMC_PCER|=0x08;
}
void AT91F_LowLevelInit(void)

{

unsigned char i;

// 1 Wait State necessary to work at 48MHz

AT91C_BASE_MC->MC_FMR = AT91C_MC_FWS_1FWS;

/////////////////////////////////////////////////////////////////////////////////////////////////////

// Init PMC Step 1. Enable Main Oscillator 使能主振荡时钟

// Main Oscillator startup time is board specific:

// Main Oscillator Startup Time worst case (3MHz) corresponds to 15ms (0x40 for AT91C_CKGR_OSCOUNT field)

/////////////////////////////////////////////////////////////////////////////////////////////////////

AT91C_BASE_PMC->PMC_MOR = (( AT91C_CKGR_OSCOUNT & (0x40 <<8) | AT91C_CKGR_MOSCEN ));

// Wait Main Oscillator stabilization

while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));

/////////////////////////////////////////////////////////////////////////////////////////////////////

// Init PMC Step 2. 配置PLL输出时钟和USB时钟 18.432 * (72+1)/14 = 96,109MHz

// Set PLL to 96MHz (96,109MHz) and UDP Clock to 48MHz

// PLL Startup time depends on PLL RC filter: worst case is choosen

// UDP Clock (48,058MHz) is compliant with the Universal Serial Bus Specification (+/- 0.25% for full speed)

/////////////////////////////////////////////////////////////////////////////////////////////////////

AT91C_BASE_PMC->PMC_PLLR = AT91C_CKGR_USBDIV_1 | AT91C_CKGR_OUT_0 | AT91C_CKGR_PLLCOUNT |

(AT91C_CKGR_MUL & (72 << 16)) | (AT91C_CKGR_DIV & 14);

// Wait for PLL stabilization

while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) );

// Wait until the master clock is established for the case we already turn on the PLL

while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );

/////////////////////////////////////////////////////////////////////////////////////////////////////

// Init PMC Step 3. 配置MCK为PLL输出分频2,处理器时钟PCK等于MCK

// Selection of Master Clock MCK (equal to Processor Clock PCK) equal to PLL/2 = 48MHz

// The PMC_MCKR register must not be programmed in a single write operation (see. Product Errata Sheet)

/////////////////////////////////////////////////////////////////////////////////////////////////////

/*
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; // 分频2

// Wait until the master clock is established

while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );

AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;//选PLL为时钟

// Wait until the master clock is established

while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );

*/
/////////////////////////////////////////////////////////////////////////////////////////////////////

// Disable Watchdog (write once register)

/////////////////////////////////////////////////////////////////////////////////////////////////////

AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;

////////////////////////////////////////////////////////////////////////////////////////////////////

// Init AIC: assign corresponding handler for each interrupt source

/////////////////////////////////////////////////////////////////////////////////////////////////////
/*
AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler ;

for (i = 1; i < 31; i++)

{

AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler ;

}

AT91C_BASE_AIC->AIC_SPU = (unsigned int) AT91F_Spurious_handler;
*/
}
//-----------------------------------------------------------------------------
int main()
{
unsigned int i=0;
// AT91F_LowLevelInit();
Init_GPIO();
Init_UART0();
//US0_init();
while(1)
{
delay(0xffff);
i=~GPIO_B->PIO_PDSR;
if((i&Key1)==Key1)
GPIO_B->PIO_CODR|=LED1;
else
GPIO_B->PIO_SODR|=LED1;
if((i&Key2)==Key2)
GPIO_B->PIO_CODR|=LED2;
else
GPIO_B->PIO_SODR|=LED2;
if((i&Key3)==Key3)
GPIO_B->PIO_CODR|=LED3;
else
GPIO_B->PIO_SODR|=LED3;
if((i&Key4)==Key4)
GPIO_B->PIO_CODR|=LED4;
else
GPIO_B->PIO_SODR|=LED4;
// i=GPIO_B->PIO_ODSR;
SendChar(0X55);
SendChar(0Xbb);
// LED_Display();
// while(!(*AT91C_US0_CSR&0x02));
// *AT91C_US0_THR=0xaa;
delay(0xffffF);
}
return 0;
}
//-------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: