CrazyBingo

受教黑金文档,再度优化兼容irq uart代码

0
阅读(3605)

主要修改了函数类型,兼容了普通和增强型中断

主要函数如下:

(1)uart_regs.h

(2)mcu_uart.h

(3)mcu_uart.c

(4)sys_main.c

//--------------------------------------------------------------------------

/*
* uart_regs.h
*
* Created on: 2011-4-4
* Author: CrazyBingo
*/

#ifndef UART_REGS_H_
#define UART_REGS_H_

#define _UART

//-----------------------------------------
typedef struct
{
//接收寄存器
union
{
struct
{
volatile unsigned long int RECEIVE_DATA :8;
volatile unsigned long int NC :24;
}BITS;
volatile unsigned long int WORD;
}RXDATA;

//収送寄存器
union
{
struct
{
volatile unsigned long int TRANSMIT_DATA :8;
volatile unsigned long int NC :24;
}BITS;
volatile unsigned long int WORD;
}TXDATA;

//状忞寄存器
union
{
struct
{
volatile unsigned long int PE :1;
volatile unsigned long int FE :1;
volatile unsigned long int BRK :1;
volatile unsigned long int ROE :1;
volatile unsigned long int TOE :1;
volatile unsigned long int TMT :1;
volatile unsigned long int TRDY :1;
volatile unsigned long int RRDY :1;
volatile unsigned long int E :1;
volatile unsigned long int NC :1;
volatile unsigned long int DCTS :1;
volatile unsigned long int CTS :1;
volatile unsigned long int EOP :1;
volatile unsigned long int NC1 :19;
}BITS;
volatile unsigned long int WORD;
}STATUS;
//控刢寄存器
union
{
struct
{
volatile unsigned long int IPE :1;
volatile unsigned long int IFE :1;
volatile unsigned long int IBRK :1;
volatile unsigned long int IROE :1;
volatile unsigned long int ITOE :1;
volatile unsigned long int ITMT :1;
volatile unsigned long int ITRDY :1;
volatile unsigned long int IRRDY :1;
volatile unsigned long int IE :1;
volatile unsigned long int TRBK :1;
volatile unsigned long int IDCTS :1;
volatile unsigned long int RTS :1;
volatile unsigned long int IEOP :1;
volatile unsigned long int NC :19;
}BITS;
volatile unsigned long int WORD;
}CONTROL;
//波特率分频器
union
{
struct
{
volatile unsigned long int BAUD_RATE_DIVISOR :16;
volatile unsigned long int NC :16;
}BITS;
volatile unsigned int WORD;
}DIVISOR;
}UART_STR;

#ifdef _UART
#define UART ((UART_STR *)UART_BASE)
#endif

#endif /* UART_REGS_H_ */

//--------------------------------------------------------------------------

/*
* uart.h
*
* Created on: 2011-4-4
* Author: CrazyBingo
*/

#ifndef MCU_UART_H_
#define MCU_UART_H_

#include "../inc/uart_regs.h"

#define BUFFER_SIZE 200
typedef struct{
unsigned char mode_flag; //xmodem 1;uart 0;
unsigned int receive_flag;
unsigned int receive_count;
unsigned char receive_buffer [BUFFER_SIZE];
alt_u8 (* send_byte) (unsigned char data);
void (* send_string) (unsigned int len, unsigned char *str);
alt_u8 (* init) (void);
alt_u8 (* baudrate) (unsigned int baudrate);
}UART_T;
extern UART_T uart;
#endif /*MCU_UART_H_*/

//--------------------------------------------------------------------------

/*
* uart.c
*
* Created on: 2011-4-4
* Author: CrazyBingo
*/

#include
#include "alt_types.h"
#include "sys/alt_irq.h"

#include "../inc/uart_regs.h"
#include "../inc/mcu_uart.h"

static alt_u8 uart_send_byte(unsigned char data);
static void uart_send_string(unsigned int len, unsigned char *str);
static alt_u8 uart_init(void);
static alt_u8 uart_set_baudrate(unsigned int baudrate);

#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
static void uart_ISR(void* context);
#else
static void uart_ISR(void* context, alt_u32 id);
#endif

//初始化 UART结构体
UART_T uart=
{
.mode_flag = 0,
.receive_flag = 0,
.receive_count = 0,
.send_byte = uart_send_byte,
.send_string = uart_send_string,
.init = uart_init,
.baudrate = uart_set_baudrate
};

//发送一个字节数据
//将发送的数据放到发送数据缓冲区内,等待状态寄存器 TRDY置 1,当 TRDY置 1,说明接收完毕
static alt_u8 uart_send_byte(unsigned char data)
{
UART->TXDATA.BITS.TRANSMIT_DATA = data;
while(!UART->STATUS.BITS.TRDY);
return 0;
}

//发送字符串
static void uart_send_string(unsigned int len, unsigned char *str)
{
while(len--)
{
uart_send_byte(*str++);
}
}

//设置波特率
static alt_u8 uart_set_baudrate(unsigned int baudrate)
{
//设置波特率:波特率 = 时钟频率/(divisor+1),转换以后就是下面了
UART->DIVISOR.WORD = (unsigned int)(ALT_CPU_FREQ/baudrate + 0.5);
return 0;
}

//初始化程序
static alt_u8 uart_init(void)
{
//默认为115200bps
uart_set_baudrate(115200);

//对控制寄寄存器的irrdy进行置1,表示当接收准备好后,中断使能
UART->CONTROL.BITS.IRRDY = 1;

//清除状态寄存器,这是处理整个寄存器的方法,大家注意
UART->STATUS.WORD = 0;

//注册uart中断,ISR为uart_ISR
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT //nios2 91 edition or later
alt_ic_isr_register
(
UART_IRQ_INTERRUPT_CONTROLLER_ID, // 中断控制器标号,从system.h复制
UART_IRQ, // 硬件中断号,从system.h复制
uart_ISR, // 中断服务子函数
0, // 指向与设备驱动实例相关的数据结构体
0 // flags,保留未用
);
#else //before nios2 91 edition
alt_irq_register
(
UART_IRQ, // 硬件中断号,从system.h复制
0, // 指向与设备驱动实例相关的数据结构体
uart_ISR // 中断服务子函数
);
#endif
return 0;
}

//串口中断
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
static void uart_ISR(void* context)
#else
static void uart_ISR(void* context, alt_u32 id)
#endif
{
//等徃状态寄存器的接收数据状态位rrdy,当rrdy位为1时,说明新接收癿值传输到了接收数据寄存器
while(!(UART->STATUS.BITS.RRDY));

//reveive_buffer为我们通过栈的方式在内存中开设内存块,将接收数据寄存器中的数据放到这个内存块中
uart.receive_buffer[uart.receive_count++] = UART->RXDATA.BITS.RECEIVE_DATA;

//当接收数据的最后一位为\n(回车符)时,进入if语句,也就是说,\n作为了结束标志
//符,每次发送数据后,要加一个回车符作为结束符
if(uart.receive_buffer[uart.receive_count - 1]=='\n')
{
uart.receive_buffer[uart.receive_count] = '\0';
uart_send_string(uart.receive_count, uart.receive_buffer);
uart.receive_count = 0;
uart.receive_flag = 1;
}
}

//--------------------------------------------------------------------------

/*
* sys_main.c
*
* Created on: 2011-4-1
* Author: CrazyBingo
* irq, timer, DMA, uart
*/

#include
#include "unistd.h"
#include "system.h"
#include "alt_types.h"
#include "sys/alt_irq.h"
#include "io.h"
#include "altera_avalon_pio_regs.h"

#include "../inc/my_sopc.h"
#include "../inc/key_scan.h"
#include "../inc/mcu_uart.h"

int main(void)
{
//------------------------------------------------------------
//uart test
unsigned char buffer[50] = "I will successfully one day!\n";
uart.init();

while(1)
{
uart.send_string(sizeof(buffer), buffer);
usleep(1000000);
}

return 0;
}

OK Go on, 谢谢

Baidu
map