我是靠谱客的博主 忧伤棒棒糖,最近开发中收集的这篇文章主要介绍nios自学笔记三:nios常用外设C函数整理一、PIO读写二、寄存器读写 三、PIO中断处理 四、定时器中断处理五、uart收发处理 六、延时函数,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
该文章为Nios II学习中的外设C函数收集整理笔记,长期更新。
提示:以下是本篇文章正文内容,下面案例可供参考
一、PIO读写
1.1 对PIO进行写操作
(1)利用给定的宏定义函数,函数原型如下:
IOWR_ALTERA_AVALON_PIO_DATA(base, data); //base是要访问的IO口的基地址,data是所要写入的数据
(2)直接调用内部函数,函数原型如下:
IOWR(BASE, REGNUM, DATA); //BASE为寄存器的基地址,REGNUM为寄存器的偏移量,DATA为要写入的数据。对于PIO来说,REGNUM为0
1.2 对PIO进行读操作
(1)利用给定的宏定义函数,函数原型如下:
value = IORD_ALTERA_AVALON_PIO_DATA(base); //base是要访问的IO口的基地址,value为函数返回的读到的值
(2)直接调用内部函数,函数原型如下:
value = IORD(BASE, REGNUM); //BASE为是要访问的IO口的基地址,REGNUM为寄存器的偏移量,value为函数返回的读到的值。对于PIO来说,REGNUM为0
二、寄存器读写
用于对momory地址内数据直接进行多bit读写,比如对RAM的读写之类的。
2.1 多位寄存器写操作
IOWR_8DIRECT(BASE, OFFSET, DATA); //往地址为BASE+OFFSET的寄存器中直接写入8Bit的数据DATA
IOWR_16DIRECT(BASE, OFFSET, DATA); //往地址为BASE+OFFSET的寄存器中直接写入16Bit的数据DATA
IOWR_32DIRECT(BASE, OFFSET, DATA); //往地址为BASE+OFFSET的寄存器中直接写入32Bit的数据DATA
2.2 多位寄存器读操作
value = IORD_8DIRECT(BASE, OFFSET); //从地址为BASE+OFFSET的寄存器中直接读8Bit的数据到value中
value = IORD_16DIRECT(BASE, OFFSET); //从地址为BASE+OFFSET的寄存器中直接读16Bit的数据到value中
value = IORD_32DIRECT(BASE, OFFSET); //从地址为BASE+OFFSET的寄存器中直接读32Bit的数据到value中
三、PIO中断处理
//需要添加的头文件
#include "system.h" // 系统
#include "altera_avalon_pio_regs.h" // PIO,ads_nIRQ
#include "alt_types.h"
#include "sys/alt_irq.h" // 中断
//相关声明
unsigned int nirq_isr_context; // 定义全局变量以储存isr_context指针
void nIRQ_Initial(void);
void nIRQ_ISR(void* isr_context);
//main函数
int main(void)
{
nIRQ_Initial(); // 初始化PIO中断
while(1)
{
}
}
// nIRQ中断初始化
void nIRQ_Initial(void)
{
void* isr_context_ptr = (void*) &nirq_isr_context; // 改写timer_isr_context指针以匹配alt_irq_register()函数原型
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(ADS_NIRQ_BASE, 1); // 使能中断
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(ADS_NIRQ_BASE, 1); // 清中断边沿捕获寄存器
// 注册ISR
alt_ic_isr_register(
ADS_NIRQ_IRQ_INTERRUPT_CONTROLLER_ID, // 中断控制器标号,从system.h复制
ADS_NIRQ_IRQ, // 硬件中断号,从system.h复制
nIRQ_ISR, // 中断服务子函数
isr_context_ptr, // 指向与设备驱动实例相关的数据结构体
0x0); // flags,保留未用
}
// 中断服务子函数
void nIRQ_ISR(void* nirq_isr_context)
{
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(ADS_NIRQ_BASE, 1); // 清中断边沿捕获寄存器
// 用户中断代码
}
四、定时器中断处理
//需要添加的头文件
#include "system.h" // 系统
#include "altera_avalon_timer_regs.h" // 定时器
#include "alt_types.h"
#include "sys/alt_irq.h" // 中断
//相关声明
unsigned int timer_isr_context; // 定义全局变量以储存isr_context指针
void Timer_Initial(void);
void Timer_ISR(void* isr_context);
//main函数
int main(void)
{
Timer_Initial(); // 初始化定时器中断
while(1)
{
}
}
// 定时器中断初始化
void Timer_Initial(void)
{
void* isr_context_ptr = (void*) &timer_isr_context; // 改写timer_isr_context指针以匹配alt_irq_register()函数原型
// 设置PERIOD寄存器
// PERIODH << 16 | PERIODL = 计数器周期因子 * 系统时钟频率因子 - 1
// PERIODH << 16 | PERIODL = 5m*100M - 1 = 499999 = 0x7A11F
IOWR_ALTERA_AVALON_TIMER_PERIODH(HIGH_RES_TIMER_BASE, 0x0007);
IOWR_ALTERA_AVALON_TIMER_PERIODL(HIGH_RES_TIMER_BASE, 0xA11F);
// 设置CONTROL寄存器
// 位数 | 3 | 2 | 1 | 0 |
// CONTROL | STOP | START| CONT | ITO |
// ITO 1,产生IRO; 0,不产生IRQ
// CONT 1,计数器连续运行直到STOP被置一; 0,计数到0停止
// START 1,计数器开始运行; 0,无影响
// STOP 1,计数器停止运行; 0,无影响
IOWR_ALTERA_AVALON_TIMER_CONTROL(
HIGH_RES_TIMER_BASE,
ALTERA_AVALON_TIMER_CONTROL_START_MSK | // START = 1
ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | // CONT = 1
ALTERA_AVALON_TIMER_CONTROL_ITO_MSK); // ITO = 1
// 注册定时器中断
alt_ic_isr_register(
HIGH_RES_TIMER_IRQ_INTERRUPT_CONTROLLER_ID, // 中断控制器标号,从system.h复制
HIGH_RES_TIMER_IRQ, // 硬件中断号,从system.h复制
Timer_ISR, // 中断服务子函数
isr_context_ptr, // 指向与设备驱动实例相关的数据结构体
0x0); // flags,保留未用
}
// 定时器中断服务子函数
void Timer_ISR(void* timer_isr_context)
{
// 应答中断,将STATUS寄存器清零
IOWR_ALTERA_AVALON_TIMER_STATUS(
HIGH_RES_TIMER_BASE,
~ ALTERA_AVALON_TIMER_STATUS_TO_MSK); // TO = 0
// 用户中断代码
}
五、uart收发处理
uart接收有查询方式和中断方式。我这里的uart接收采用中断处理方式,发送利用单独的函数实时处理。
5.1 uart发送函数
//查询发送准备好信号,如果没有准备好,则等待
while(!((IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE)&ALTERA_AVALON_UART_STATUS_TRDY_MSK)));
//发送准备好,发送txbyte
IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE,txbyte);
5.2 uart中断接收
//相关头文件
#include "system.h" //系统硬件信息的宏定义文件
#include "alt_types.h" //与Nios II相关的数据类型
#include "altera_avalon_uart_regs.h" //提供相应内核寄存器访问宏定义
#include "sysalt_irq.h" //中断相关宏定义
//相关声明
unsigned int uart_isr_context; //定义全局变量以储存isr_context指针
void uart_init();
static void uart_isr(void * p_uart_isr_context);
//main函数
int main(void)
{
uart_init(); // 初始化uart中断
while(1)
{
}
}
//uart中断初始化
void uart_init()
{
// 改写pack_uart_isr_context指针以匹配alt_irq_register()函数原型
void *isr_context_ptr = (void*) & uart_isr_context;
//清除状态寄存器
IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE,0);
//使能接受准备好中断
IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0X80);
// 注册ISR
alt_ic_isr_register(
UART_0_IRQ_INTERRUPT_CONTROLLER_ID, // 中断控制器标号,从system.h复制
UART_0_IRQ, // 硬件中断号,从system.h复制
uart_isr, // 中断服务子函数
isr_context_ptr, // 指向与设备驱动实例相关的数据结构体
0x0); // flags,保留未用
}
//uart中断接收服务子函数
static void uart_isr(void * p_uart_isr_context)
{
//清除状态寄存器
IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE,0);
//用户逻辑
//rxdata = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);//UART 接收
/*
//查询发送准备好信号,如果没有准备好,则等待
while(!((IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE)&ALTERA_AVALON_UART_STATUS_TRDY_MSK)));
//发送准备好,发送txdata
IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE,txdata);
*/
}
六、延时函数
//所需头文件
#include "unistd.h"
//us延时函数 usleep()
usleep(200*1000); //延时200ms
注:usleep()函数做ms级别及以上的延时的确很准,但是us级别就有点捉襟见肘了。如果是us级别的延时可以用for()循环做空语句延时,但是这样也只是粗略的延时。
最后
以上就是忧伤棒棒糖为你收集整理的nios自学笔记三:nios常用外设C函数整理一、PIO读写二、寄存器读写 三、PIO中断处理 四、定时器中断处理五、uart收发处理 六、延时函数的全部内容,希望文章能够帮你解决nios自学笔记三:nios常用外设C函数整理一、PIO读写二、寄存器读写 三、PIO中断处理 四、定时器中断处理五、uart收发处理 六、延时函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复