七月二十四日作业

mychrdev.c

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/io.h>

#include "head.h"

#include "stm32mp1xx_gpio.h"

unsigned int major;//定义一个变量保存主设备号

char kbuf[128]={0};

unsigned int *vir_rcc;

//LED1

unsigned int *vir_led1_moder;

unsigned int *vir_led1_odr;

//LED2

unsigned int *vir_led2_moder;

unsigned int *vir_led2_odr;

//LED3

unsigned int *vir_led3_moder;

unsigned int *vir_led3_odr;

//

gpio_t *vir_GPIOE;

gpio_t *vir_GPIOF;


 

//封装操作方法

int mycdev_open(struct inode *inode, struct file *file)

{

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

}

ssize_t mycdev_read(struct file *file, char  *ubuf, size_t size, loff_t *lof)

{

     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

      long ret;

     ret=copy_to_user(ubuf,kbuf,size);

     if(ret)

     {

        printk("copy_to_user filed\n");

        return -EIO;

     }

    return 0;

}

ssize_t mycdev_write(struct file *file, const char  *ubuf, size_t size, loff_t *lof)

{

     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

      long ret;

     ret=copy_from_user(kbuf,ubuf,size);

     if(ret)

     {

        printk("copy_from_user filed\n");

        return -EIO;

     }

     //判断用户输入的数据,进行不同的硬件逻辑执行

     if(kbuf[0]=='0')//关灯

     {

        //关灯逻辑

        //LED1

        (*vir_led1_odr) &= (~(0X1<<10));

        //LED2

        (*vir_led2_odr) &= (~(0X1<<10));

        //LED3

        (*vir_led3_odr) &= (~(0X1<<8));

     }

     else if(kbuf[0]=='1')

     {

        //开灯逻辑

        //LED1

        (*vir_led1_odr) |=(0X1<<10);

        //LED2

        (*vir_led2_odr) |=(0x1<<10);

        //LED3

        (*vir_led3_odr) |=(0x1<<8);

     }

    return 0;

}

int mycdev_close(struct inode *inode, struct file *file)

{

     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

}

//定义一个操作方法结构体变量并且初始化

struct file_operations fops={

    .open=mycdev_open,

    .release=mycdev_close,

    .read=mycdev_read,

    .write=mycdev_write,

};

static int __init mycdev_init(void)

{

    //注册字符设备驱动

    major=register_chrdev(0,"mychrdev",&fops);

    if(major<0)

    {

        printk("注册字符设备驱动失败\n");

        return major;

    }

    printk("注册字符设备驱动成功major=%d\n",major);

    //进行寄存器地址的映射

    //LED1

    vir_led1_moder=ioremap(PHY_LED1_MODER,4);

    if(vir_led1_moder==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

    vir_led1_odr=ioremap(PHY_LED1_ODR,4);

    if(vir_led1_odr==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

   

    //LED2

    vir_led2_moder=ioremap(PHY_LED2_MODER,4);

    if(vir_led2_moder==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

    vir_led2_odr=ioremap(PHY_LED2_ODR,4);

    if(vir_led2_odr==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

    //LED3

    vir_led3_moder=ioremap(PHY_LED3_MODER,4);

    if(vir_led3_moder==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

    vir_led3_odr=ioremap(PHY_LED3_ODR,4);

    if(vir_led3_odr==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

/*

   //GPIOE映射

   vir_GPIOE=ioremap(GPIOE,0x30);

    if(vir_GPIOE==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

     //GPIOF映射

   vir_GPIOF=ioremap(GPIOE,0x30);

    if(vir_GPIOF==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

    //RCC映射

    vir_rcc=ioremap(PHY_LED_RCC,4);

    if(vir_rcc==NULL)

    {

        printk("映射物理内存失败%d\n",__LINE__);

        return -EFAULT;

    }

    printk("映射物理内存成功\n");

    //硬件寄存器的初始化

    //RCC使能

    (*vir_rcc)|=(0X3<<4);//rcc使能

    //LED1

    (*vir_led1_moder) &=(~(0X3<<20));//设置为输出

    (*vir_led1_moder) |=(0X1<<20);

    (*vir_led1_odr) &= (~(0X1<<10));//输出低电平

    printk("硬件寄LED1存器初始化成功\n");

    //LED2

    (*vir_led2_moder) &=(~(0X3<<20));//设置为输出

    (*vir_led2_moder) |=(0X1<<20);

    (*vir_led2_odr) &= (~(0X1<<8));//输出低电平

    printk("硬件LED2寄存器初始化成功\n");

    //LED3

    (*vir_led3_moder) &=(~(0X3<<16));//设置为输出

    (*vir_led3_moder) |=(0X1<<16);

    (*vir_led3_odr) &= (~(0X1<<10));//输出低电平

    printk("硬件LED3寄存器初始化成功\n");

    */

   /*

    //LED1

    vir_GPIOE->MODER &= (~(0X3<<20));//设置为输出

    vir_GPIOE->MODER |=(0X1<<20);

    vir_GPIOE->ODR &= (~(0x1 << 10));

    //LED2

    vir_GPIOF->MODER &= (~(0X3<<20));//设置为输出

    vir_GPIOF->MODER |=(0X1<<20);

    vir_GPIOF->ODR &= (~(0x1 << 8));//输出低电平

    //LED3

    vir_GPIOE->MODER &= (~(0X3<<16));//设置为输出

    vir_GPIOE->MODER |=(0X1<<16);

    vir_GPIOE->ODR &= (~(0x1 << 10));//输出低电平

*/

    return 0;

}

static void __exit mycdev_exit(void)

{

    //注销字符设备驱动

    unregister_chrdev(major,"mychrdev");

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

head.h

#ifndef __HEAD_H__

#define __HEAD_H__

#ifndef __STM32MP1xx_GPIO_H__

#define __STM32MP1xx_GPIO_H__

#define PHY_LED_RCC   0X50000A28

#define PHY_LED1_MODER 0X50006000

#define PHY_LED1_ODR   0X50006014


 

#define PHY_LED2_MODER 0X50007000

#define PHY_LED2_ODR   0X50007014


 

#define PHY_LED3_MODER 0X50006000

#define PHY_LED3_ODR   0X50006014

typedef struct {

    volatile unsigned int MODER;   // 0x00

    volatile unsigned int OTYPER;  // 0x04

    volatile unsigned int OSPEEDR; // 0x08

    volatile unsigned int PUPDR;   // 0x0C

    volatile unsigned int IDR;     // 0x10

    volatile unsigned int ODR;     // 0x14

    volatile unsigned int BSRR;    // 0x18

    volatile unsigned int LCKR;    // 0x1C

    volatile unsigned int AFRL;    // 0x20

    volatile unsigned int AFRH;    // 0x24

    volatile unsigned int BRR;     // 0x28

    volatile unsigned int res;

    volatile unsigned int SECCFGR; // 0x30

}gpio_t;

#define  GPIOA   ((gpio_t *)0x50002000)

#define  GPIOB   ((gpio_t *)0x50003000)

#define  GPIOC   ((gpio_t *)0x50004000)

#define  GPIOD   ((gpio_t *)0x50005000)

#define  GPIOE   (0x50006000)

#define  GPIOF   (0x50007000)

#define  GPIOG   ((gpio_t *)0x50008000)

#define  GPIOH   ((gpio_t *)0x50009000)

#define  GPIOI   ((gpio_t *)0x5000A000)

#define  GPIOJ   ((gpio_t *)0x5000B000)

#define  GPIOK   ((gpio_t *)0x5000C000)

#define  GPIOZ   ((gpio_t *)0x54004000)


 

#endif // __STM32MP1xx_GPIO_H__

tese.c

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdlib.h>

#include <string.h>

int main(int argc, char const *argv[])

{

    char buf[128] = {0};

    int fd = open("/dev/mychrdev", O_RDWR);

    if (fd < 0)

    {

        printf("打开设备文件失败\n");

        exit(-1);

    }

    while (1)

    {

        printf("请输入控制命令:0(关灯)1(开灯)>");

        fgets(buf, sizeof(buf), stdin); // 从终端输入数据到buf

        buf[strlen(buf) - 1] = '\0';    // 将buf末尾的'\n'切换为'\0'

        write(fd, buf, sizeof(buf));

    }

    close(fd);

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个相对复杂的大作业,需要涉及到公历、农历的计算和转换。下面是一个简单的实现思路: 1. 首先需要实现公历相关的计算,包括判断某一年是否为闰年、计算某一年某一月的天数、计算某一日是该年的第几天等。 2. 接下来需要实现农历相关的计算,包括农历年份的计算、农历月份的计算、农历日期的计算等。这部分可以使用已有的算法或者库函数进行计算。 3. 实现万年历的显示,可以使用控制台输出或者GUI界面显示。在显示时需要注意公历和农历的转换,并且需要考虑到节气、节日等特殊情况的显示。 下面是一个简单的代码示例,实现了基本的公历和农历转换和万年历显示: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MIN_YEAR 1900 #define MAX_YEAR 2100 // 公历计算相关函数 int is_leap_year(int year); int days_of_month(int year, int month); int days_of_year(int year, int month, int day); // 农历计算相关函数 int lunar_year(int year); int lunar_month(int year, int month, int day); int lunar_day(int year, int month, int day); char* lunar_month_name(int month); // 万年历显示函数 void print_calendar(int year, int month, int day); int main() { int year, month, day; // 获取当前时间 time_t t = time(NULL); struct tm* tm = localtime(&t); year = tm->tm_year + 1900; month = tm->tm_mon + 1; day = tm->tm_mday; // 显示万年历 print_calendar(year, month, day); return 0; } int is_leap_year(int year) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { return 1; } return 0; } int days_of_month(int year, int month) { int days; switch (month) { case 2: days = is_leap_year(year) ? 29 : 28; break; case 4: case 6: case 9: case 11: days = 30; break; default: days = 31; break; } return days; } int days_of_year(int year, int month, int day) { int days = day; for (int i = 1; i < month; i++) { days += days_of_month(year, i); } return days; } int lunar_year(int year) { int lunar_year = 0; int delta = year - MIN_YEAR; int leap_years = delta / 4 - delta / 100 + delta / 400; lunar_year = delta * 365 + leap_years; return lunar_year; } int lunar_month(int year, int month, int day) { int lunar_month = 0; int days = days_of_year(year, month, day); for (int i = 1; i <= 12; i++) { int leap = ((i == 2 && is_leap_year(year)) ? 1 : 0); if (days <= (29 + leap)) { lunar_month = i; break; } days -= (29 + leap); } return lunar_month; } int lunar_day(int year, int month, int day) { int lunar_day = 0; int days = days_of_year(year, month, day); int leap_month = lunar_month(year, month, day); for (int i = 1; i <= days; i++) { lunar_day++; if (lunar_day > 29 + ((leap_month == 2 && is_leap_year(year)) ? 1 : 0)) { lunar_day = 1; leap_month = (leap_month == 12) ? 1 : leap_month + 1; } } return lunar_day; } char* lunar_month_name(int month) { char* name = ""; switch (month) { case 1: name = "正月"; break; case 2: name = "二月"; break; case 3: name = "三月"; break; case 4: name = "四月"; break; case 5: name = "五月"; break; case 6: name = "六月"; break; case 7: name = "七月"; break; case 8: name = "八月"; break; case 9: name = "九月"; break; case 10: name = "十月"; break; case 11: name = "冬月"; break; case 12: name = "腊月"; break; } return name; } void print_calendar(int year, int month, int day) { printf("公历:%d年%d月%d日\n", year, month, day); int lunar_y = (lunar_year(year) + days_of_year(year, month, day) - 1) / 29.5; int lunar_m = lunar_month(year, month, day); int lunar_d = lunar_day(year, month, day); printf("农历:%d年%s%d日\n", lunar_y, lunar_month_name(lunar_m), lunar_d); // TODO: 万年历显示 } ``` 在上面的代码中,我们实现了公历和农历的转换,并且可以输出基本的公历和农历信息。下一步需要实现万年历的显示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值